commit fe3e0cdfd3a8c76eba78e7868def866178ae8aa7
Author: Jocelyn Delande <jocelyn at delalande dot fr>
Date:   Sun Nov 17 19:31:46 2013 +0100

    - Moved ref_points.php to something less toulouse-specific ;-)
    by default : no ref points, but the ability to define its own list
    or to use one of the files from ref_points folder.
    - Fixed the UI if the ref_points list is empty.

diff --git a/.gitignore b/.gitignore
index cc6e167..924dd63 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 upload/
 tiles/
-*~
\ No newline at end of file
+*~
+ref_points.local.php
\ No newline at end of file
diff --git a/README.md b/README.md
index b7bf450..43a0ebc 100644
--- a/README.md
+++ b/README.md
@@ -19,10 +19,17 @@ Features
 * **view on map** for a given LOS between two points/panoramas.
 
 
-Known Limitations
------------------
+Setting up reference points
+----------------------------
 
-* The reference points are hardcoded in ref_points.php
+Reference points are known points you are likely to see from your panoramas,
+they are a visual reference and a way to orientate your panoramas.
+
+By default, there are no *ref_points*, you can create your own *ref_points* list
+or use one of the provided lists.
+
+To get started, copy one of the files from `ref_points` folder in the root
+folder, remane it to `ref_points.local.php` and customize it.
 
 Panorama view
 --------------
@@ -35,8 +42,6 @@ menu allows you to set the orientation of your panorama by pointing at a known
 location you visualize on the panorama.
 
 
-
-
 ### Mouse interaction for panorama view ###
 
 * *drag image*  to move
diff --git a/js/pano.js b/js/pano.js
index 1a14e6b..41a0413 100644
--- a/js/pano.js
+++ b/js/pano.js
@@ -38,11 +38,11 @@ var test = {x:0, y:0, i:100};
 
 
 function nmodulo(val, div) {                // pour obtenir un modulo dans l'espace des nombres naturels N.
-    return Math.floor((val%div+div)%div);   // il y a peut être plus simple, mais en attendant .... 
+    return Math.floor((val%div+div)%div);   // il y a peut être plus simple, mais en attendant ....
 }
 
 function fmodulo(val, div) {                // pour obtenir un modulo dans l'espace des nombres réels positifs.
-    return (val%div+div)%div;               // il y a peut être plus simple, mais en attendant .... 
+    return (val%div+div)%div;               // il y a peut être plus simple, mais en attendant ....
 }
 
 function distort_canvas(p, x, y) {
@@ -64,21 +64,21 @@ function distort_canvas(p, x, y) {
 
 function draw_image(ox, oy) {
     var ref_vals  = {x:last.x, y:last.y, zoom:zoom};
-    ox = nmodulo(ox-canvas.width/2, zm.im.width);        // pour placer l'origine au centre du canvas 
+    ox = nmodulo(ox-canvas.width/2, zm.im.width);        // pour placer l'origine au centre du canvas
     oy = Math.floor(oy-canvas.height/2);                 // pas de rebouclage vertical
 
     cntext.clearRect(0, 0, canvas.width, canvas.height);
     cntext.fillStyle = "rgba(128,128,128,0.8)";
-    
+
     if (canvas.height > zm.im.height) {
 	var fy = Math.floor((oy+canvas.height/2-zm.im.height/2)/(tile.height*zm.ntiles.y))*zm.ntiles.y;
-	if (fy < 0) fy = 0; 
+	if (fy < 0) fy = 0;
 	var ly = fy + zm.ntiles.y;
     } else {
 	var fy = Math.floor(oy/tile.height);
 	var ly = Math.floor((oy+canvas.height+tile.height-1)/tile.height+1);
-	if (fy < 0) fy = 0; 
-	if (ly > zm.ntiles.y) ly = zm.ntiles.y; 
+	if (fy < 0) fy = 0;
+	if (ly > zm.ntiles.y) ly = zm.ntiles.y;
     }
 
     for (var j=fy; j<ly; j++) {
@@ -141,7 +141,7 @@ function drawDecorations(ox, oy, tx, ty, twidth, theight) {
 	cntext.beginPath();
         cntext.rect(tx, ty, twidth, theight);
         cntext.clip();
-    } 
+    }
     var wgrd = zm.im.width/360;
     var od = ((ox+canvas.width/2)/wgrd)%360;
     var el = (zm.im.height/2 - (oy+canvas.height/2))/wgrd;
@@ -164,7 +164,7 @@ function drawDecorations(ox, oy, tx, ty, twidth, theight) {
     if (twidth) {
 	cntext.restore();
     }
-    
+
 }
 
 function insert_drawn_point(lat, lon, alt) {
@@ -179,19 +179,19 @@ function insert_drawn_point(lat, lon, alt) {
     var alt2 = alt;
     var lat2 = lat*Math.PI/180;
     var lon2 = lon*Math.PI/180;
-    
+
     var dLat = lat2-lat1;
-    var dLon = lon2-lon1; 
-   
-    var a = Math.sin(dLat/2)*Math.sin(dLat/2) + Math.sin(dLon/2)*Math.sin(dLon/2)*Math.cos(lat1)*Math.cos(lat2);  // 
+    var dLon = lon2-lon1;
+
+    var a = Math.sin(dLat/2)*Math.sin(dLat/2) + Math.sin(dLon/2)*Math.sin(dLon/2)*Math.cos(lat1)*Math.cos(lat2);  //
     var angle = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
     var d = angle*rt;                    // distance du point en Kms
-   
+
     var y = Math.sin(dLon) * Math.cos(lat2);
     var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
     var cap = Math.atan2(y,x);                 // cap pour atteindre le point en radians
     var e = Math.atan2((alt2 - alt1)/1000 - d*d/(2*rt),d);  // angle de l'élévation en radians
-    
+
     return {d:d, cap:cap*180/Math.PI, ele:e*180/Math.PI};   // les résultats sont en degrés
 }
 
@@ -216,7 +216,7 @@ function localate_point() {
     display_temp(opt_dce.d, opt_dce.cap, opt_dce.ele);
 }
 
-function display_temp(d,cap,ele) {  
+function display_temp(d,cap,ele) {
     point_list[point_list.length] = new Array("point temporaire", d,cap,ele, "temporary");
     reset_zooms();
     putImage(last.x, last.y);
@@ -226,15 +226,15 @@ function arrayUnset(array, value){
     array.splice(array.indexOf(value), 1);
 }
 
-function erase_point() {	
+function erase_point() {
 	for (var i=0; i<point_list.length; i++) {
 		if(point_list[i][0] == "point temporaire"){
 			arrayUnset(point_list,point_list[i]);
 			loop = erase_point();
-		}	
-	}	
+		}
+	}
 	reset_zooms();
-    putImage(last.x, last.y);   
+    putImage(last.x, last.y);
 }
 
 function get_file_name(x, y, z) { // recherche du fichier correspondant au zoom et à la position
@@ -251,7 +251,7 @@ function get_file_name(x, y, z) { // recherche du fichier correspondant au zoom
 }
 
 function keys(key) {
-	
+
     hide_links();
     evt = key || event;
     //evt.preventDefault();
@@ -343,7 +343,7 @@ function launchImage(e) {
 }
 
 function putImage(x, y) { // est destiné à permettre l'effet d'amortissement par la mémorisation de la position courante.
-    if (!zm.is_updated) return; 
+    if (!zm.is_updated) return;
     if (x >= zm.im.width) {   // rebouclage horizontal
 	shift.x -= zm.im.width;
 	x -= zm.im.width;
@@ -411,7 +411,7 @@ function tzoom(zv) {
 	ord_pts = ord_pts.sort(tri_ref_points);
 	is_located = i > 1 || image_loop && i > 0;
 
-	var alpha_domain = {start:0, end:360}; 
+	var alpha_domain = {start:0, end:360};
 	this.pixel_y_ratio = this.im.width/360;
 	if (is_located) {
 	    this.ref_pixels = new Array;
@@ -514,11 +514,11 @@ function tzoom(zv) {
 		typ = 'loc_point';
 	    }else if(is_visible && lbl =='point temporaire') {
 	    typ = 'temporary';
-	    
+
 	    } else if(is_visible) {
 		typ = 'pano_point';
 		lnk += '&to_zoom='+this.value;
-	    } 
+	    }
 	    this.pt_list[i]['type'] = typ;
 	    this.pt_list[i]['cap'] = cap;
 	    this.pt_list[i]['ele'] = ele;
@@ -529,7 +529,7 @@ function tzoom(zv) {
 	    this.pt_list[i]['yc'] = Math.floor(this.im.height/2 - rxy.y);
 	}
     }
-    
+
     this.get_tile_size = function(nx, ny) {
 	var res = {width:0, height:0};
 	if (nx == this.ntiles.x-1) res.width = this.last_tile.width;
@@ -538,7 +538,7 @@ function tzoom(zv) {
 	else res.height = this.tile.height;
 	return res;
     }
-    
+
     this.get_cap_ele = function(px, py) {               // recherche d'un cap et d'une élévation à partir d'un pixel X,Y.
 	if (is_located) {
 	    for (var i=0; i < this.ref_pixels.length; i++) {
@@ -555,7 +555,7 @@ function tzoom(zv) {
 	    return {cap:cp, ele:el};
 	}
     }
-    
+
     this.get_pos_xy = function(cap, ele) {                  // recherche des coordonnées pixel à partir d'un cap et d'une élévation.
 	if (is_located) {
 	    var dcap = fmodulo(cap-this.ref_pixels[0].cap, 360);
@@ -591,7 +591,7 @@ function wheel_zoom (event) {
 	zoom_control.value++;
 	change_zoom(zshift.x, zshift.y);
     } else if (event.wheelDelta > 0 && zoom_control.value > zoom_control.min) {
-	zoom_control.value--; 
+	zoom_control.value--;
 	change_zoom(zshift.x, zshift.y);
     }
 }
@@ -637,7 +637,7 @@ function change_angle() {
     putImage(pos_x, pos_y);
 }
 
-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. 
+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.
     return Math.sqrt(x*x + y*y) < r;
 }
 
@@ -702,35 +702,43 @@ function hide_contextmenu() {
     document.getElementById('insert').style.display = 'none';
 }
 
-function manage_ref_points(e) {
+function manage_ref_points(e, has_points) {
     //event.preventDefault();
     //event.stopPropagation();
-    var insrt = document.getElementById('insert');
-    document.getElementById('do-cancel').onclick = hide_contextmenu;
-    insrt.style.left = e.pageX+'px';
-    insrt.style.top = e.pageY+'px';
-    insrt.style.display = 'block';
-    var sel_pt = document.getElementById('sel_point');
+	var sel_pt = document.getElementById('sel_point');
     var do_insert = document.getElementById('do-insert');
-    var do_delete = document.getElementById('do-delete');
-    var show_cap = document.getElementById('show-cap');
+	var do_delete = document.getElementById('do-delete');
+	var do_cancel = document.getElementById('do-cancel');
+	var show_cap = document.getElementById('show-cap');
+	var insrt = document.getElementById('insert');
+
     var pos_x = nmodulo(last.x + e.pageX - canvas_pos.x - canvas.width/2, zm.im.width);
-    var pos_y = last.y + e.pageY - canvas_pos.y - canvas.height/2;
-    for(var i = 0; i < zm.pt_list.length; i++) {
-	if (zm.pt_list[i]['type'] == 'ref_point') {
-	    if (check_prox(zm.pt_list[i]['xc']-pos_x, zm.pt_list[i]['yc']-pos_y, 20)) {
-		sel_pt.value = zm.pt_list[i]['label'];
-	    }
+	var pos_y = last.y + e.pageY - canvas_pos.y - canvas.height/2;
+
+	insrt.style.left = e.pageX+'px';
+	insrt.style.top = e.pageY+'px';
+	insrt.style.display = 'block';
+
+	if (has_points) {
+		    for(var i = 0; i < zm.pt_list.length; i++) {
+			    if (zm.pt_list[i]['type'] == 'ref_point') {
+				    if (check_prox(zm.pt_list[i]['xc']-pos_x,
+				                   zm.pt_list[i]['yc']-pos_y, 20)) {
+					    sel_pt.value = zm.pt_list[i]['label'];
+				    }
+			    }
+		    }
+		do_delete.onclick = function() {delete_ref_point(insrt)};
+		do_insert.onclick = function() {insert_ref_point(insrt, e.pageX-canvas_pos.x, e.pageY-canvas_pos.y)};
+		show_cap.onclick = function() {
+			window.open('show_capline.php?title='+encodeURIComponent(btoa(title))+'&cap='+res.cap+'&org_lat='+pt_lat+'&org_lon='+pt_lon+'&dist=120000');
+		};
 	}
-    }
-    do_delete.onclick = function() {delete_ref_point(insrt)};
-    do_insert.onclick = function() {insert_ref_point(insrt, e.pageX-canvas_pos.x, e.pageY-canvas_pos.y)};
+
+	do_cancel.onclick = hide_contextmenu;
     var res = zm.get_cap_ele(pos_x, zm.im.height/2 - pos_y);
     var pt_lat = document.getElementById('pos_lat').childNodes[0].nodeValue;
     var pt_lon = document.getElementById('pos_lon').childNodes[0].nodeValue;
-    show_cap.onclick = function() {
-	window.open('show_capline.php?title='+encodeURIComponent(btoa(title))+'&cap='+res.cap+'&org_lat='+pt_lat+'&org_lon='+pt_lon+'&dist=120000');
-    };
     return false;
 }
 
@@ -794,31 +802,31 @@ canvas_resize = function() {
 }
 
 function paramIn(e) {
-    e = e || window.event; 
-    var relatedTarget = e.relatedTarget || e.fromElement; 
-    
+    e = e || window.event;
+    var relatedTarget = e.relatedTarget || e.fromElement;
+
     while (relatedTarget != adding && relatedTarget.nodeName != 'BODY' && relatedTarget != document && relatedTarget != localisation) {
 	relatedTarget = relatedTarget.parentNode;
     }
-    
+
     if (relatedTarget != adding && relatedTarget != localisation) {
 	document.removeEventListener('keydown', keys, false);
     }
 }
 
 function paramOut(e) {
-	 
-    e = e || window.event; 
-    var relatedTarget = e.relatedTarget || e.toElement; 
- 
+
+    e = e || window.event;
+    var relatedTarget = e.relatedTarget || e.toElement;
+
     while (relatedTarget != adding && relatedTarget.nodeName != 'BODY' && relatedTarget != document && relatedTarget != localisation) {
         relatedTarget = relatedTarget.parentNode;
     }
- 
+
     if (relatedTarget != adding && relatedTarget != localisation) {
     	document.addEventListener('keydown', keys, false);
     }
- 
+
 }
 
 window.onload = function() {
diff --git a/panorama.php b/panorama.php
index 8cf65cc..1c6cc50 100644
--- a/panorama.php
+++ b/panorama.php
@@ -15,20 +15,20 @@
   <label class="form_col" title="L'altitude positive Ex: 170">Altitude :
     <input  name="loca_altitude" type="number" min="-400" id="loca_altitude"/></label>
   <div class="answer">
-    <input type="button" value="Localiser" id="loca_button"/> 
+    <input type="button" value="Localiser" id="loca_button"/>
     <input type="button" value="Effacer" id="loca_erase"/>
   </div>
 </fieldset>
 EO_FORM_EXTPOINT;
 
    $form_param = <<<'EO_FORM_PARAM'
-<div id="addParams">		
-  <label id="paramFormShow">Paramétrer le panorama</label>	
+<div id="addParams">
+  <label id="paramFormShow">Paramétrer le panorama</label>
 </div>
      <form action="addParams.php?param_dir=%s&amp;param_panorama=%s" id="form_param" method="post">
   <fieldset id="adding"><legend id="paramFormHide">Paramétrage du panorama</legend>
     <label title="Au moins 4 caractères">Titre :
-      <input type="text" pattern="^.{1,40}$" name="param_title" placeholder="%s" 
+      <input type="text" pattern="^.{1,40}$" name="param_title" placeholder="%s"
 	     title="ne doit pas contenir pus de 40 caractères" required=""/></label>
     <label title="La latitude ϵ [-90°, 90°]. Ex : 46.55257">Latitude :
       <input name="param_latitude" type="number" min="-90" max="90" placeholder="43.56" required="" step="any"/></label>
@@ -38,9 +38,9 @@ EO_FORM_EXTPOINT;
       <input name="param_altitude" type="number" min="-400" required="" placeholder="170" step="any"/></label>
     <label title="L'image fait-elle 360° ?">Rebouclage :
       <input type="checkbox" name="param_loop" value="true"></label>
-    
+
     <div>
-      <input type="submit" value="Submit"/> 
+      <input type="submit" value="Submit"/>
       <input type="reset" value="Reset"/>
     </div>
   </fieldset>
@@ -110,8 +110,11 @@ EO_FORM_PARAM;
        printf('point_list[%d] = new Array("%s", %03lf, %03lf, %03lf, "%s");'."\n", $ipt++, $prm['titre'], $dist, $cap, $ele, $lnk);
      }
    }
-
-   include 'ref_points.php';
+   $ref_points = array ();
+   $ref_points_filename = 'ref_points.local.php';
+   if (file_exists($ref_points_filename)) {
+     include $ref_points_filename;
+   }
    $extra_names = array();
    $ref_names = array();
    if (is_array($ref_points)) {
@@ -122,7 +125,7 @@ EO_FORM_PARAM;
        printf('point_list[%d] = new Array("%s", %03lf, %03lf, %03lf, "");'."\n", $ipt++, $name, $dist, $cap, $ele);
      }
    }
- 
+
 
    if (isset($params['reference'])) {
      echo "ref_points = new Array();\n";
@@ -134,27 +137,27 @@ EO_FORM_PARAM;
        }
      }
    }
-  
+
    $localLat = (isset($_POST["loca_latitude"])) ? $_POST["loca_latitude"] : NULL;
    $localLon = (isset($_POST["loca_longitude"])) ? $_POST["loca_longitude"] : NULL;
    $localAlt = (isset($_POST["loca_altitude"])) ? $_POST["loca_altitude"] : NULL;
- 
+
    if ($localLat && $localLon && $localAlt) {
      list($localDistance, $localCap, $localEle) = $pt->coordsToCap($localLat, $localLon, $localAlt);
      $n = "point temporaire";
      printf('point_list[%d] = new Array("%s", %03lf, %03lf, %03lf, "temporary");'."\n",$ipt++, $n, $localDistance, $localCap, $localEle);
-   } 
+   }
   ?>
   </script>
   <link type="image/x-icon" rel="shortcut icon" href="images/tsf.png"/>
   <link rel="stylesheet" media="screen" href="css/map.css" />
-  <script src="js/hide_n_showForm.js"></script> 
+  <script src="js/hide_n_showForm.js"></script>
 </head>
 <body>
   <canvas id="mon-canvas">
     Ce message indique que ce navigateur est vétuste car il ne supporte pas <samp>canvas</samp> (IE6, IE7, IE8, ...)
   </canvas>
-  
+
   <fieldset id="control"><legend>contrôle</legend>
       <label>Zoom : <input type="range" min="0" max="2" value="2" id="zoom_ctrl"/></label>
       <label>Cap : <input type="number" min="0" max="360" step="10" value="0" autofocus="" id="angle_ctrl"/></label>
@@ -162,12 +165,12 @@ EO_FORM_PARAM;
   </fieldset>
 
   <?php
-      
+
      if ($params && isset($params['latitude']) && isset($params['longitude'])) {
        print("<div id=\"params\">\n");
        printf ("<p>latitude :   <em><span id=\"pos_lat\">%.5f</span>°</em></p>\n", $params['latitude']);
        printf ("<p>longitude : <em><span id=\"pos_lon\">%.5f</span>°</em></p>\n", $params['longitude']);
-       if (isset($params['altitude'])) printf ("<p>altitude : <em><span id=\"pos_alt\">%d</span> m</em></p>\n", $params['altitude']); 
+       if (isset($params['altitude'])) printf ("<p>altitude : <em><span id=\"pos_alt\">%d</span> m</em></p>\n", $params['altitude']);
        print("</div>\n");
        echo $form_extpoint;
      } elseif ($params == false ) {
@@ -176,19 +179,22 @@ EO_FORM_PARAM;
         printf($form_param, $dir, $name, $name);
      }
      echo '<p id="info"></p>'."\n";
+
+     echo "<p id=\"insert\">";
      if (count($extra_names) > 1) {
-       echo "<p id=\"insert\">\n<select id=\"sel_point\" name=\"known_points\">\n";
+       echo "<select id=\"sel_point\" name=\"known_points\">\n";
        foreach ($extra_names as $nm) {
-	 echo '<option>'.$nm."</option>\n";
+	     echo '<option>'.$nm."</option>\n";
        }
        echo "</select>\n";
        echo "<input type=\"button\" id=\"do-insert\" value=\"insérer\"/>\n";
        echo "<input type=\"button\" id=\"do-delete\" value=\"suppimer\"/>\n";
-       echo "<input type=\"button\" id=\"do-cancel\" value=\"annuler\"/>\n";
        echo "<input type=\"button\" id=\"show-cap\" value=\"visualiser cet axe sur OSM\"/>\n";
-       echo "</p>\n";
+     } else {
+       echo "Pas de point de reférénce connu, lisez le <em>README.md</em> pour en ajouter. \n";
      }
-     
+     echo "<input type=\"button\" id=\"do-cancel\" value=\"annuler\"/>\n";
+     echo "</p>\n";
   ?>
   <p id="res"></p>
   <div class="validators">
diff --git a/ref_points.php b/ref_points/ref_points-toulouse-ttnn.php
similarity index 100%
rename from ref_points.php
rename to ref_points/ref_points-toulouse-ttnn.php
