Version 2.0 – septembre 2003
Voici le code source du script.
<?xml version="1.0" encoding="iso-8859-1"?> <svg xml:lang="fr" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ced="./cedricExtensions" xmlns:a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" height="100%" width="100%" onload="init(evt)" onzoom="resizeOnZoom()" > <!-- I removed the a3:scriptImplementation="Adobe" statements because I found it incredibly slow with hi-res data. The embedded parses takes 1.5 secs to do the _same_ job as Adobe's one in 1 hour... so I made my choice..... :o] --> <!-- viewBox="0 0 1000 536" --> <title>Zones du monde</title> <desc xml:lang="fr"> Cédric Kiss -- SWAD-Europe / W3C -- Un projet IST -- 2003. Cette carte repère des zones, localise des personnes, et affiche en RDF quelles zones sont communes à une position (entrée à la souris). </desc> <!-- Analyseur syntaxique RDF de Jim Ley <script xlink:href="rdfparser.seeAlso.js" type="text/ecmascript" a3:scriptImplementation="Adobe"/> --> <!-- Crypteur SHA1 pour les adresses mail --> <script xlink:href="sha1.js" type="text/ecmascript"/> <!-- a3:scriptImplementation="Adobe" --> <defs> <style type="text/css"><![CDATA[ circle{stroke-width: 0.2px; opacity: 0.6;} text{font-size: 7pt;} .countryOutlines{opacity: .5; fill: orange; stroke: none;} .countryOutline1{opacity: .5; fill: orange; stroke: none;} .countryOutline2{opacity: .5; fill: yellow; stroke: none;} .countryOutline3{opacity: .5; fill: purple; stroke: none;} .countryOutline4{opacity: .5; fill: red; stroke: none;} .countryOutline5{opacity: .5; fill: blue; stroke: none;} .airportIcao{opacity: 0.6; fill: yellow;} .airportIata{opacity: 0.6; fill: red;} .actor{opacity: 0.7; fill: white; stroke: black;} .graduation{font-family: courier new; font-weight: bold; font-size: 22pt;} .texteTravail{font-size: 30pt;} #airportName{font-size: 10pt;} #actorsAtAirport{font-size: 8pt;} #credits{fill: black;} #scriptResults{font-family: courier new; font-size: 10pt;} ]]></style> <rect id="bouton" height="20" width="40" fill="red" rx="2" stroke="black" /> <g id="compteur"> <path id="compteur_fond" d="M -100 0 L 0 0 L 100 0 A 100 100 0 0 0 -100 0 Z" fill="white"/> <path id="compteur_remplissage" stroke="white" fill="orange" d="" /> <path id="compteur_contour" d="M -100 0 L 0 0 L 100 0 A 100 100 0 0 0 -100 0 Z" stroke="black" stroke-width="1.6" fill="none"/> <text x="-95" y="-5" class="graduation">0%</text> <text x="95" y="-5" class="graduation" style="text-anchor: end;">100%</text> <path id="aiguille" transform="scale(1,1.7)" fill="yellow" stroke="black" d="M 0 -2 l -92 0 l 0 -3 l -15 5 l 15 5 l 0 -3 l 92 0 A 3 3 0 0 0 0 -2 Z" /> <text x="112" y="-52" class="texteTravail">Travail en cours : <tspan x="112" y="0" id="texteTravailEnCours" class="texteTravail">N/A.</tspan> </text> </g> </defs> <metadata> author: Cédric Kiss - http://ckiss.net/cedric created: May to August 2003 homepage: http://www.w3.org/2001/sw/Europe/200306/geo/readme_carte_zones_monde_rdf.html Part of W3C SWAD-Europe project. </metadata> <!-- 'onclick' attributes : traceOutlines(evt) to draw manually the outlines of a country on the map (deprecated) locateMousePoint(evt) to discover the region of a given point --> <g id="world_map" onclick="locateMousePoint(evt)"> // (fr) On imagine que le monde a une largeur de 1000 pixels, et on l'affiche // (en) Assume the world's width is 1000 pixels and start drawing ! <rect id="mapBackground" x="0" y="0" width="1000" height="500" fill="lightblue"/> <image opacity="0.8" xlink:href="images/cartes/Day_lrg.jpg" width="1000" height="500"/> <image opacity="0.535" xlink:href="images/cartes/utmworld_ced.png" x="-20" y="17" width="1052.4" height="479.6"/> <g id="world_outlines" style="visibility: visible;"> <zoneType>Planete</zoneType> <title>Planete Terre</title> <g id="europe_outlines"> <zoneType>Continent</zoneType> <title>Europe</title> <!-- (fr) Note : les 'd' doivent tenir sur une seule ligne --> <!-- (en) Notice: 'd' descriptions should be single-lined --> <g id="france_outlines"> <zoneType>Pays</zoneType> <title>France</title> <g id="france_outlines_lowres"> <!-- (fr) Utiliser lorsque aucune autre donnée n'est disponible --> <!-- (en) Use when there is no other data available --> <g> <zoneType>Autres</zoneType> <path id="fralt000001" class="countryOutlines" d="M 508.25 134.25 L 496.0625 129.5625 L 496.5625 122.25 L 492.9375 118.8125 L 486.875 116.9375 L 487.125 115.5 L 494.9375 115.0625 L 494.9375 112.25 L 499.8125 113.4375 L 504.8125 108.625 L 507.3125 108.4375 L 521.1875 113.9375 L 520 118 L 516.375 121.5625 L 518.5625 123.3125 L 520.125 128.9375 L 517.4375 131 L 510.75 129.25 L 508.25 130.8125 Z"/> </g> <g> <zoneType>Région</zoneType> <title>PACA</title> <path class="countryOutlines" d="M 520.2 128.8125 L 517.575 131 L 511.375 129.5375 L 512.1875 126.625 L 518.875 124.4375 Z"/> </g> <g> <zoneType>Autres</zoneType> <title>Corsica</title> <path id="fralt000002" class="countryOutlines" d="M 526.1875 131.25 L 526.25 133.5625 L 525.25 135.4375 L 524.0625 133.875 L 524.1875 132.125 L 525.4375 132 Z"/> </g> </g> </g> <g id="spain_outlines"> <zoneType>Pays</zoneType> <title>Spain</title> <g> <!-- Use when there is no other data available --> <path class="countryOutlines" d="M 496.125 129.4375 L 477.5625 129 L 474.4375 130.6875 L 476 133.0625 L 482.5625 133.3125 L 480.375 146.9375 L 484.4375 150.1875 L 486.75 148.1875 L 494.4375 147.875 L 499.4375 142.75 L 500.6875 138.375 L 505.5 135.8125 L 508.1875 134.25 Z"/> </g> <!-- order doesnt matter --> <g> <zoneType>Région</zoneType> <title>Galicia</title> <path idd="slfqhblh" class="countryOutlines" d="M 482.5 129.125 L 477.375 129 L 474.375 130.6875 L 475.9375 132.9375 L 482.625 133.0625 Z" /> </g> </g> <g id="unitedKingdom_outlines"> <zoneType>Pays</zoneType> <precision>0</precision> <title>United Kingdom</title> <!-- Use when there is no other data available --> <g> <zoneType>Île</zoneType> <title>Main Island</title> <path id="unitedKingdom_main" class="countryOutlines" d="M 485.1875 111.375 L 501.5625 109.375 L 504.1875 104.6875 L 492.375 94.25 L 494.6875 90.1875 L 488.75 90.1875 L 491.5625 87.5 L 486.0625 87.6875 L 481.875 93.875 L 486.5625 98.4375 L 491.6875 100.3125 L 491.25 102.5 L 487.375 101.5625 L 485.9375 106.875 L 489.5625 107.3125 Z"/> </g> </g> <g id="poland_outlines"> <zoneType>Pays</zoneType> <title>Poland</title> <g id="poland_outlines_alt"> <!-- Use when there is no other data available --> <path id="poland_main" class="countryOutlines" d="M 563.5625 99.4375 L 548.5625 97.875 L 541.0625 99.9375 L 540.4375 107.6875 L 555.3125 114.125 L 561.375 114.125 L 565.8125 108.5 Z"/> </g> </g> </g> <g> <zoneType>Continent</zoneType> <title>Asia</title> <g type="pays"> <zoneType>Pays</zoneType> <title>Russie</title> <path class="countryOutlines" d="M 582 56 L 577 93 L 631 133 L 635.5 108.5 L 695.5 98 L 792 133 L 840.5 99.5 L 872 129.5 L 892 99.5 L 881 94.5 L 948 78 L 934.5 93.5 L 938 104.5 L 960.5 81 L 998.5 69.5 L 999.5 57 L 813 42 L 786 33.5 L 695.5 43 L 617 62 L 581 54.5 Z"/> </g> </g> </g> </g> <g id="dessins"> </g> <g id="carteActors"> <!-- Contient les éléments graphiques pour la localisation des acteurs --> </g> <g id="carteAirports"> <!-- Contient les éléments graphiques pour la localisation des aéroports --> </g> <g id="textes"> <text x="10" y="490" id="yourCurrentLocation">Vous avez choisi cette position : <tspan id="yourCurrentLocationName">Aucune</tspan> <tspan id="yourCurrentLocationCoords">()</tspan> </text> <text x="10" y="475" id="line1">M </text> <text id="airportName"> </text> <text id="actorsAtAirport"> </text> </g> <g id="credits"> <rect x="0" y="500" width="1000" height="36" fill="#d0d0d0" rx="4"/> <a xlink:href="http://www.w3.org/2001/sw/Europe/"> <image xlink:href="images/logos/swadelogo2.png" x="896" y="502" height="32" width="28" /> </a> <a xlink:href="http://www.w3.org/"> <image xlink:href="images/logos/w3c.gif" x="930" y="502" height="32" width="59" /> </a> </g> <g id="results"> <text x="10" y="20" id="scriptResults"> </text> </g> <text x="10" y="515" style="font-size: 9pt;">En développement <tspan x="10" y="530"><a xlink:href="http://ckiss.net/cedric" style="fill: blue;">Cédric Kiss</a>, août 2003</tspan> </text> <use xlink:href="#compteur" transform="translate(250,533) scale(0.3)"/> <g id="boutons"> <g transform="translate(530,506) scale(0.5)" onclick="afficheActors()"> <use xlink:href="#bouton"/> <text x="46" y="20" style="font-size: 20pt;">Afficher les acteurs</text> </g> <g transform="translate(530,522) scale(0.5)" onclick="afficheAirportsCoords()"> <use xlink:href="#bouton"/> <text x="46" y="20" style="font-size: 20pt;">Afficher les aéroports</text> </g> <g transform="translate(700,506) scale(0.5)" onclick="afficheResults()"> <use xlink:href="#bouton"/> <text x="46" y="20" style="font-size: 20pt;">Afficher les résultats</text> </g> <g transform="translate(700,522) scale(0.5)" onclick="afficheStatsChargement()"> <use xlink:href="#bouton"/> <text x="46" y="20" style="font-size: 20pt;">Bilan des fichiers chargés</text> </g> </g> <script type="text/ecmascript"><![CDATA[ // a3:scriptImplementation="Adobe" // === Début du script ==================================================== var svgDocu; var mapWidth; var mapHeight; /* // Create RDF object myRDF=new RDF(); myAirports=new RDF(); // Déclaration des Namespaces foafNS="http://xmlns.com/foaf/0.1/" aptNS="http://xmlns.com/wordnet/1.6/"; contactNS="http://www.w3.org/2000/10/swap/pim/contact#"; airNS="http://www.megginson.com/exp/ns/airports#"; */ // the lower (=1) the better (thus the slower) var precision=20; // Pas encore fait var arrayMesSubZones; // Colorado --> www.whitehouse.gov ; Corse --> www.elysee.fr var mesAirportsCoords=new Array(); // 1:{IATA,ICAO,Nom,(43N,2E)}... var mesActors=new Array(); // mailto:cedric2003@ckiss.net --> Coords( ... , ... , ... ) // c125e43d1e4526784fe8... --> Coords(...) var foafFilesToLoad=new Array(); // Dernières coordonnées cliquées var lastClickedCoords; var proximityResults=new Array(); // actor / zone / type_zone // "vous etes dans zone, c'est à dire le meme type_zone que actor." // Éléments graphiques... var diametrePointsAirports=4.5; var diametrePointsActors=2.2; // Gestion du chargement de données externes sur des codes aéroport inconnus var externalAdvicesOnAirports=0; var conditionElement; var conditionValue; // <foaf:interest>Machin</foaf:interest> // (fr) Filtrage des personnes selon un critère (laisser conditionValue vide pour ne pas filtrer) // (en) You can set a condition to include a person to the graph or not (leave conditionValue blank to include everyone) conditionElement='foaf:interest'; conditionValue=''; // Exemple : ceux qui auront 'w3' contenu dans leur 'foaf:interest' var nombreFichiersFoafCharges=0; var nombreFichiersFoafNonCharges=0; var nombreFichiersAreaCharges=0; var nombreFichiersAreaNonCharges=0; var nFichiersFoafEnCours=0; var nFichiersFoafTotal=0; var nombreAirportCoordsExternes=0; var nombreAirportCoordsExternesRecus=0; // The path to your (PHP?) proxy (change this to match your config) // Sur mon laptop //var pathToProxy='http://localhost/rdfig/proxy.php'; // Sur le dossier public var pathToProxy='http://www.w3.org/2001/sw/Europe/200306/geo/proxy.php'; function init(evt){ svgDocu=evt.getTarget().getOwnerDocument(); if(conditionValue) svgDocu.getElementById('line1').firstChild.nodeValue='Filtrage des personnes selon '+conditionElement+' : '+conditionValue+'.'; else svgDocu.getElementById('line1').firstChild.nodeValue='(Pas de filtrage des personnes)'; // État du script svgDocu.getElementById('texteTravailEnCours').firstChild.nodeValue='Chargement du script'; // Dimensions de la carte (utile pour les conversions) mapHeight=svgDocu.getElementById('mapBackground').getAttribute('height'); mapWidth=svgDocu.getElementById('mapBackground').getAttribute('width'); // État du script svgDocu.getElementById('texteTravailEnCours').firstChild.nodeValue='Chargement des aéroports'; // (fr) Afficher les aéroports // 4 aéroports //getURL('airports-test.rdf',drawAirportsFromFile); // 8000 aéroports ? getURL('airports.rdf.gz',drawAirportsFromFile); // Un peu de temporisation setTimeout('initsuite1()',3000) } function initsuite1(){ // État du script svgDocu.getElementById('texteTravailEnCours').firstChild.nodeValue='Chargement des pays'; // Les outlines des pays //getURL('outlines/belgium2pts.rdf',drawAreaFromFile); //getURL('outlines/germany2pts.rdf',drawAreaFromFile); getURL('outlines/usa_outlines.rdf',drawAreaFromFile); getURL('outlines/europe_outlines.rdf',drawAreaFromFile); // État du script svgDocu.getElementById('texteTravailEnCours').firstChild.nodeValue='Chargement des fichiers FOAF'; // Get an individual Foaf file? //myRDF.getRDFURL(pathToProxy+'?url=http://ckiss.net/cedric/foaf.rdf',getFoafActorInfo) //myRDF.getRDFURL(pathToProxy+'?url=http://www.petebarrwatson.com/pm/foaf.rdf',getFoafActorInfo) // Get a set of Foaf files //loadFOAFScutter(pathToProxy+'?url=http://jibbering.com/scutter/'); // (Fichier local) loadFOAFScutter('scutter_20030806.xml'); } function loadFOAFScutter(url){ //alert('getAllFOAFFromFile : connexion à '+url); getURL(url,readFOAFScutter); } function readFOAFScutter(urlRequestStatus){ if(!urlRequestStatus.success) { alert('Impossible de charger le scutter de fichiers FOAF !'); return(false); } var msg=urlRequestStatus.content; //alert('File loaded : '+msg.substr(0,80)+'...'); var externNode = parseXML(msg,svgDocu); // Nombre de fichiers à charger nFichiersFoafTotal+=externNode.firstChild.getElementsByTagName('rdfs:seeAlso').length try{ // A toujours marché var myFiles=externNode.firstChild.getElementsByTagName('rdfs:seeAlso'); }catch(erreur){ // Je le mets au cas où ? var myFiles=externNode.firstChild.nextSibling.getElementsByTagName('rdfs:seeAlso'); } for(var a=0; a<myFiles.length; a++){ currentFile=myFiles.item(a).getAttribute('rdf:resource'); // Si on ne l'a déjà pas chargée //if(foafFilesToLoad.isInArray(currentFile)==-1){ foafFilesToLoad.push(currentFile); getURL(pathToProxy+'?url='+currentFile,getFoafActorInfo); //} // Si on ne veut pas charger plus de 'n' fichiers... if(a==140){ //break; } } } function afficheActorNamesAtAirport(code){ // Affiche sur la carte la liste des Actors à un Airport donné var afficheActorNames=''; var nActeurs=0; for(var a=0; a<mesActors.length; a++){ if(mesActors.item(a).aptCode==code){ afficheActorNames+=mesActors.item(a).name+', '; nActeurs++; } } afficheActorNames=afficheActorNames.substring(0,afficheActorNames.length-2); if(nActeurs){ // On retrouve les coords var coords=getAirportCoords(code); if(coords){ var ax=longitudeToSVGCoordinatesMercator(coords.lon); var ay=latitudeToSVGCoordinatesMercator(coords.lat); } var scale=svgDocu.documentElement.getCurrentScale(); svgDocu.getElementById('actorsAtAirport').setAttribute('x',ax+(5/scale)); svgDocu.getElementById('actorsAtAirport').setAttribute('y',ay+(13/scale)); } svgDocu.getElementById('actorsAtAirport').firstChild.nodeValue=afficheActorNames; } function afficheResults(){ if(!lastClickedCoords){ alert('afficheResults : il faut cliquer d\'abord quelque part !'); return(false); } //alert('afficheResults : Proximity Test...\n'+lastClickedCoords); lastClickedCoords.proximityTest(); } function afficheLastClickedCoords(){ if(lastClickedCoords.lat){ //alert('afficheLastClickedCoords : '+lastClickedCoords.lat+','+lastClickedCoords.lon); svgDocu.getElementById('yourCurrentLocationCoords').firstChild.nodeValue='('+lastClickedCoords.lat+','+lastClickedCoords.lon+')'; }else window.alert('Vous n\'avez pas cliqué \nlastClickedCoords='+lastClickedCoords); } function resizeOnZoom(){ var scale=svgDocu.documentElement.getCurrentScale(); var lesCircles=svgDocu.getElementById('carteAirports').getElementsByTagName('circle'); // Taille des points des aéroports for(var i=0; i<lesCircles.length; i++) { lesCircles.item(i).setAttribute('r',(diametrePointsAirports/scale)); } // Taille du texte nommant l'aéroport var taille=(10/scale); svgDocu.getElementById('airportName').setAttribute('style','font-size: '+taille+'pt;'); // Taille du texte nommant les personnes à l'aéroport var taille=(8/scale); svgDocu.getElementById('actorsAtAirport').setAttribute('style','font-size: '+taille+'pt;'); var lesCircles=svgDocu.getElementById('carteActors').getElementsByTagName('circle'); // Taille des points des acteurs for(var i=0; i<lesCircles.length; i++) { lesCircles.item(i).setAttribute('r',(diametrePointsActors/scale)); // Pourquoi ça ne marche pas ??? //lesCircles.item(i).setAttribute('stroke-width',(0.5/scale)); } } function getAirportCoords(code){ // Renvoie les Coords() d'un aéroport désigné par son code IATA ou ICAO var codeType=getCodeType(code); var coordsFound=false; for(var a=0; a<mesAirportsCoords.length; a++){ //alert('on compare '+code+' à '+mesAirportsCoords[a].icao+' ou à '+mesAirportsCoords[a].iata); if(codeType=='iata' && mesAirportsCoords[a].iata){ if(code==mesAirportsCoords[a].iata){ coordsFound=mesAirportsCoords[a].coords; break; } } else { if(code==mesAirportsCoords[a].icao){ coordsFound=mesAirportsCoords[a].coords; break; } } } if(!coordsFound){ // On a un code d'aéroport mais on ne trouve pas les coordonnées... //alert('Pas de coordonnées trouvées pour l\'aéroport de code '+codeType+' : <'+code+'>... GoTo JLAL'); // (fr) Ajouter au nombre d'aéroports externes demandés externalAdvicesOnAirports++; // (fr) Demander au Jim Ley Airport Locator getURL(pathToProxy+'?url=http://jibbering.com/foaf/airports.1?'+code,getAirportCoordsFromAirportLocator); nombreAirportCoordsExternes++; // Temporisation pour que 2 fichiers ne soient pas 'confondus' (bug d'ecmascript) setTimeout('rien()',2000); } //alert('coordsFound : '+coordsFound); return(coordsFound); } function getAirportCoordsFromAirportLocator(urlRequestStatus){ // On accède un service en ligne qui envoie des fichiers RDF à la demande ! // On décrémente le compteur externalAdvicesOnAirports--; if(!urlRequestStatus.success) { //alert('Impossible de charger le fichier RDF du Jim Ley Airport Locator !'); return(false); } var msg=urlRequestStatus.content; //alert('JimLeyAirportLocator-FileLoaded: '+msg.substr(0,200)+'...\nlength : '+msg.length); // (fr) On va tenter de trouver les coordonnées de cet aéroport var coordsAirport=false; if(msg.substr(0,6)=='erreur'){ // Could not reach destination, or any other error my proxy could have encountered... return(false); } var externNode = parseXML(msg,svgDocu); //alert('msg='+msg); // Permet de 'sauter' jusqu'à 100 lignes de commentaires : <!-- blah blah --> // Si quelqu'un a une meilleure idée, qu'il me la donne ! var myAirport=false; for(var a=0; a<100; a++){ try{ myAirport=externNode.childNodes.item(a).getElementsByTagName('airport:Airport'); }catch(erreur){} if(myAirport){ //alert('trouvé après '+a+' lignes de commentaires'); break; } } if(myAirport.length){ myAirport=myAirport.item(0); //alert('loca : '+myAirport.getElementsByTagName('airport:location').item(0).firstChild.nodeValue); try{ if(myAirport.getElementsByTagName('pos:lat').length){ var lat=myAirport.getElementsByTagName('pos:lat').item(0).firstChild.nodeValue; var lon=myAirport.getElementsByTagName('pos:long').item(0).firstChild.nodeValue; } }catch(erreur){ //alert('getAirportCoordsFromAirportLocator : Encore une erreur : '+erreur+'\nmsg='+msg); return(false); } nombreAirportCoordsExternesRecus++; if(myAirport.getElementsByTagName('airport:location').length){ if(myAirport.getElementsByTagName('airport:location').item(0).firstChild){ try{ var name=myAirport.getElementsByTagName('airport:location').item(0).firstChild.nodeValue; }catch(erreur){ alert('Erreur airport:location : '+erreur); alert('myAirport : '+myAirport); alert('1 myAirport.getElementsByTagName(airport:location) : '+myAirport.getElementsByTagName('airport:location')); //alert('2 myAirport.getElementsByTagName(airport:location) : '+printNode(myAirport.getElementsByTagName('airport:location'))); alert('1 myAirport.getElementsByTagName(airport:location).item(0) : '+myAirport.getElementsByTagName('airport:location').item(0)); alert('2 myAirport.getElementsByTagName(airport:location).item(0) : '+printNode(myAirport.getElementsByTagName('airport:location').item(0))); name="Nom inconnu (1)"; } } }else var name="Nom inconnu (2)"; // (fr) Le code de l'aéroport n'est pas dans le RDF ! Je le récupère à partir du nom de fichier... :-( var about=myAirport.getAttribute('rdf:about'); //alert('code : '+about); var code=about.substr(about.indexOf('?')+1); var codeType=getCodeType(code); //alert('code donc : '+code+' ... '+codeType); coordsAirport=new Coords(lat,lon); if(codeType=='iata'){ var iata=code; var icao=null; } else { var iata=null; var icao=code; } // Ajouter les résultats au tableau var apt=new Airport(name,coordsAirport,iata,icao); // Faire des vérifs pour savoir si l'aéroport n'était pas dans // le tableau, ou s'il y était mais mal renseigné var uniqueName=true; for(var a=0; a<mesAirportsCoords.length; a++){ //alert('on compare '+name+' et '+mesAirportsCoords[a].name); if(name==mesAirportsCoords[a].name){ uniqueName=false; break; } } if(uniqueName){ // Test supplémentaire : le code existe-t-il déjà dans le tableau ? var uniqueCode=true; for(var a=0; a<mesAirportsCoords.length; a++){ //alert('on compare '+name+' et '+mesAirportsCoords[a].name); if(name==mesAirportsCoords[a].name){ uniqueCode=false; break; } } } if(uniqueName==false){ // Modif au rang 'a' s'il manquait les coordonnées if(!mesAirportsCoords[a].coords){ mesAirportsCoords[a].coords=coordsAirport; } // Modif au rang 'a' s'il manquait le code if(codeType=='iata'){ if(!mesAirportsCoords[a].iata) mesAirportsCoords[a].iata=code; }else{ if(!mesAirportsCoords[a].icao) mesAirportsCoords[a].icao=code; } }else if(uniqueCode==false){ // Modif au rang 'a' s'il manquait les coordonnées if(!mesAirportsCoords[a].coords) mesAirportsCoords[a].coords=coordsAirport; if(!mesAirportsCoords[a].name) mesAirportsCoords[a].name=name; }else{ mesAirportsCoords.push(apt); apt.draw(); } // On update 'rétrospectivement' la table des Actors if(externalAdvicesOnAirports==0){ // Si on n'attend plus d'autre fichier, on peut traiter les acteurs qui restaient sans coordonnées resolveActorsAvecAirportSansCoords(); } } } function getCodeType(code){ // (en) Detects 3-letter codes (iata) and 4-letter codes (icao) if(code.length==3){ var codeType='iata'; }else if(code.length==4){ var codeType='icao'; }else{ window.alert(code+' n\'est pas un code d\'aéroport valable !'); return(false); } return(codeType); } function getAirportName(code){ // Renvoie les Coords() d'un aéroport désigné par son code IATA ou ICAO // (en) Detects 3-letter codes (iata) and 4-letter codes (icao) if(code.length==3){ var codeType='iata'; }else if(code.length==4){ var codeType='icao'; }else{ window.alert(code+' n\'est pas un code d\'aéroport valable !'); return(false); } var nameFound=false; for(var a=0; a<mesAirportsCoords.length; a++){ //alert('on compare '+code+' à '+mesAirportsCoords[a].icao+' et à '+mesAirportsCoords[a].iata); if(codeType=='iata'){ if(code==mesAirportsCoords[a].iata){ nameFound=mesAirportsCoords[a].name; break; } } else { if(code==mesAirportsCoords[a].icao){ nameFound=mesAirportsCoords[a].name; break; } } } //alert('nameFound : '+nameFound); return(nameFound); } function getImmediateChildrenByTagName(node,givenTagName){ // (fr) Trouve les éléments 'givenTagName' _immédiatement_ fils d'un node var myNodeList=new Array(); var mesTags=node.getElementsByTagName(givenTagName); for(var a=0; a<mesTags.length; a++){ if(mesTags.item(a).parentNode==node){ myNodeList.push(mesTags.item(a)); //if(givenTagName=='foaf:mbox') //alert('Accepté : '+printNode(mesTags.item(a))); //}else{ //if(givenTagName=='foaf:mbox') //alert('Refusé : '+printNode(mesTags.item(a))); } } return(myNodeList); } function getFoafActorInfo(urlRequestStatus){ // Nombre de fichiers à charger nFichiersFoafEnCours++; actualiseCompteurFichiersCharges(nFichiersFoafEnCours,nFichiersFoafTotal); // État du script if(nFichiersFoafEnCours==nFichiersFoafTotal) svgDocu.getElementById('texteTravailEnCours').firstChild.nodeValue='Chargement des fichiers FOAF terminé.'; else svgDocu.getElementById('texteTravailEnCours').firstChild.nodeValue='Chargement des fichiers FOAF ('+nFichiersFoafEnCours+'/'+nFichiersFoafTotal+')'; if(!urlRequestStatus.success) { //alert('Impossible de charger le fichier FOAF !'); nombreFichiersFoafNonCharges++; return(false); } var msg=urlRequestStatus.content; //alert('getFoafActorInfo : FileLoaded: '+msg.substr(0,80)+'...\nlength : '+msg.length); if(msg.substr(0,6)=='erreur'){ // Could not reach destination, or any other error my proxy could have encountered... nombreFichiersFoafNonCharges++; return(false); } else nombreFichiersFoafCharges++; var externNode = parseXML(msg,svgDocu); //alert('msg='+msg); // Permet de 'sauter' jusqu'à 100 lignes de commentaires : <!-- blah blah --> // Si quelqu'un a une meilleure idée, qu'il me la donne ! var myPersons=false; for(var a=0; a<100; a++){ try{ myPersons=externNode.childNodes.item(a).getElementsByTagName('foaf:Person'); }catch(erreur){} if(myPersons){ //alert('trouvé après '+a+' lignes de commentaires'); break; } } var coords,myLat,myLon,iata,icao,mailbox; for(var a=0; a<myPersons.length; a++){ // On regarde d'abord si la Person est intéressante pour notre programme // Note : ici on recherche conditionValue dans TOUT le RDF de conditionElement, c.-à.-d., <foaf:interest><rdf:Description .... </> // C'est assez laid ; il faudra pouvoir rechercher dans les Attributs et les Valeurs mais pas dans les Éléments. if(conditionValue){ conditionFound=false; // Recherche de l'élément qui fait la condition ? //condition=myPersons.item(a).getElementsByTagName(conditionElement); // Maintenant condition=getImmediateChildrenByTagName(myPersons.item(a),conditionElement); if(condition.length){ //alert('Condition trouvée : '+condition.length+' élément(s) \n'); for(var b=0; b<condition.length; b++){ //alert(printNode(condition.item(b))); if(printNode(condition.item(b)).indexOf(conditionValue)!==-1){ conditionFound=true; //alert('condition '+conditionValue+' trouvée dans\n'+printNode(condition.item(b))); break; } } } }else{ // Sans condition, c'est toujours d'accord conditionFound=true; } // On n'ajoute la personne que si elle répond à notre condition // (ou s'il n'y a pas de condition définie) if(conditionFound){ // Recherche des coordonnées géographiques coords=false; // Si l'utilisateur fournit ses coordonnées // <geo:location><geo:Position geo:lat="52.422400" geo:lon="-0.803000"/></geo:location> position=false; position=myPersons.item(a).getElementsByTagName('geo:location'); if(position.length){ try{ position=position.item(0).getElementsByTagName('geo:Position'); }catch(erreur){ /* alert('getFoafActorInfo : Erreur '+erreur+'\n(1) position='+position); alert('msg='+msg); alert('(2) position.item(0)='+position.item(0)); alert('(3) printNode(position)='+printNode(position)); alert('(4) printNode(position.item(0))='+printNode(position.item(0))); */ } if(position.length){ try{ myLat=position.item(0).getAttribute('geo:lat'); myLon=position.item(0).getAttribute('geo:lon'); coords=new Coords(myLat,myLon); //alert('getFoafActorInfo : on a une geo:position !!\n'+coords); }catch(erreur){ //alert('encore une erreur : '+erreur); } } } iata=''; icao=''; // Pas nécéssaire maintenant ? if(!coords){ // Recherche en fonction de l'aéroport le plus proche nearest=getImmediateChildrenByTagName(myPersons.item(a),'contact:nearestAirport'); if(nearest.length){ // Recherche du code de l'aéroport ; du style <wn:Airport air:iata="NCE"/> //apt=nearest.item(0).getElementsByTagName('wn:Airport'); apt=getImmediateChildrenByTagName(nearest.item(0),'wn:Airport'); /* // (Besoin d'une ontologie pour traiter wn:Airport <==> airport:Airport) if(apt.length!=1) alert('Avertissement :\nnearestAirport demandé ; pourtant, nombre d\'aéroports='+apt.length); */ // Récupération des coordonnées de la personne par son aéroport if(apt.length){ myLat=apt.item(0).getAttribute('pos:lat'); myLon=apt.item(0).getAttribute('pos:long'); if(myLat && myLon && !coords){ // Si les coordonnées sont déjà fournies coords=new Coords(myLat,myLon); alert('getFoafActorInfo : myLat && myLon : pas encore testé\n'+coords); }else{ // Si les coordonnées ne sont pas fournies, on regarde dans nos tables iata=apt.item(0).getAttribute('air:iata'); icao=apt.item(0).getAttribute('air:icao'); //alert('code IATA : '+iata+'\ncode ICAO : '+icao); if(iata){ if(!coords) coords=getAirportCoords(iata); //alert('Recherche avec iata='+iata); } if(!coords){ if(icao){ if(!coords){ coords=getAirportCoords(icao); //alert('Recherche avec icao='+icao); } } } } } } } // Sans coordonnées géographiques, pas d'intérêt à garder les personnes if(coords || iata || icao){ // On associe les acteurs aux coordonnées géographiques name=''; if(getImmediateChildrenByTagName(myPersons.item(a),'foaf:name').length){ name=getImmediateChildrenByTagName(myPersons.item(a),'foaf:name').item(0).firstChild.nodeValue; } else if(getImmediateChildrenByTagName(myPersons.item(a),'foaf:givenname').length){ name=getImmediateChildrenByTagName(myPersons.item(a),'foaf:givenname').item(0).firstChild.nodeValue; } else if(getImmediateChildrenByTagName(myPersons.item(a),'foaf:nick').length){ name=getImmediateChildrenByTagName(myPersons.item(a),'foaf:nick').item(0).firstChild.nodeValue; } else if(getImmediateChildrenByTagName(myPersons.item(a),'foaf:surname').length){ name=getImmediateChildrenByTagName(myPersons.item(a),'foaf:surname').item(0).firstChild.nodeValue; } if(iata) aptCode=iata; else if(icao) aptCode=icao; else aptCode=''; photoUri='NotSet'; foafUri='NotSet'; // On rentre toutes les adresses mail de la personne (car ce sont ses identifiants) // et sans mettre celles des autres, naturellement //alert('on get les mailbox'); // GRR mesMailboxesNonCryptees=myPersons.item(a).getImmediateChildrenByTagName('foaf:mbox'); mesMailboxesNonCryptees=getImmediateChildrenByTagName(myPersons.item(a),'foaf:mbox'); for(var b=0; b<mesMailboxesNonCryptees.length; b++){ mailbox=mesMailboxesNonCryptees.item(b).getAttribute('rdf:resource'); //mailbox=hex_sha1(mailbox); if(coords || aptCode){ newActor=new Actor(name,mailbox,coords,aptCode,photoUri,foafUri); //alert('Nom de la personne : '+name+'\nmailbox : '+mailbox+'\niata : '+iata+'\nicao : '+icao+'\naptCode retenu : '+aptCode+'\nCoords : \n'+coords); // Vérification qu'il n'est pas déjà dans le tableau (code -1 ; sinon : position) if(newActor.actorIsInArray(mesActors)==-1){ mesActors.push(newActor); if(coords) newActor.draw(); } } } //mesMailboxesCryptees=myPersons.item(a).getElementsByTagName('foaf:mbox_sha1sum'); // Maintenant mesMailboxesCryptees=getImmediateChildrenByTagName(myPersons.item(a),'foaf:mbox_sha1sum'); for(var b=0; b<mesMailboxesCryptees.length; b++){ mailbox=mesMailboxesCryptees.item(b).firstChild.nodeValue; if(coords || aptCode){ newActor=new Actor(name,mailbox,coords,aptCode,photoUri,foafUri); //alert('Nom de la personne : '+name+'\nmailbox : '+mailbox+'\niata : '+iata+'\nicao : '+icao+'\naptCode retenu : '+aptCode+'\nCoords : \n'+coords); // Vérification qu'il n'est pas déjà dans le tableau if(newActor.actorIsInArray(mesActors)==-1){ mesActors.push(newActor); if(coords) newActor.draw(); } } } } } } } function actualiseCompteurFichiersCharges(nFichiersFoafEnCours,total){ // (fr) Angle de l'aiguille, en degrés (100% correspond à 180 degrés) var rota=((nFichiersFoafEnCours/total)*100)*1.8; svgDocu.getElementById('aiguille').setAttribute('transform','rotate('+rota+') scale(1,1.7)'); // (fr) En radians... var rota=rota/180*Math.PI; var x1=-100*Math.cos(rota); var y1=-100*Math.sin(rota); var myPath='M -100 0 L 0 0 L '; myPath+=x1+' '+y1; myPath+=' A 100 100 0 0 0 -100 0 Z'; svgDocu.getElementById('compteur_remplissage').setAttribute('d',myPath); } function afficheAirportsCoords(){ var alertMesAirportsCoords='Liste des '+mesAirportsCoords.length+' AirportsCoords\n=====================\n'; for(var a=0; a<mesAirportsCoords.length; a++){ if(mesAirportsCoords[a].iata) alertMesAirportsCoords+=mesAirportsCoords[a].iata+' \t'; else alertMesAirportsCoords+=' \t'; if(mesAirportsCoords[a].icao) alertMesAirportsCoords+=mesAirportsCoords[a].icao+' \t'; else alertMesAirportsCoords+=' \t'; alertMesAirportsCoords+=mesAirportsCoords[a].name+' \t('+mesAirportsCoords[a].coords.lon+','+mesAirportsCoords[a].coords.lat+')\n'; if(a%30==29){ alert(alertMesAirportsCoords+'\n[Continuer...]'); alertMesAirportsCoords=''; } } alert(alertMesAirportsCoords+'\n[Fin]'); } function afficheActors(){ // On affiche le plus de coordonnées possible (même si tous les aéroports 'externes' ne nous sont pas encore parvenus) resolveActorsAvecAirportSansCoords(); var alertMesActors='Liste des '+mesActors.length+' Actors\n====================\n'; for(var a=0; a<mesActors.length; a++){ //alertMesActors+=mesActors[a].name+' : \t('+mesActors[a].coords.lat+','+mesActors[a].coords.lon+')\n'; alertMesActors+=mesActors[a].name+' \t<'+mesActors[a].mbox+'> : \t'+mesActors[a].aptCode+'\t('+mesActors[a].coords.lat+','+mesActors[a].coords.lon+')'; alertMesActors+='\n'; } alert(alertMesActors); } function resolveActorsAvecAirportSansCoords(){ var coords,codeActor,codeType=false; for(var a=0; a<mesActors.length; a++){ // Si on a le code mais pas les coordonnées if(mesActors[a].aptCode && !mesActors[a].coords){ codeActor=mesActors[a].aptCode; codeType=getCodeType(codeActor); if(!codeType) continue; // et pas break ? coords=false; for(var b=0; b<mesAirportsCoords.length; b++){ if(codeType=='iata'){ if(codeActor==mesAirportsCoords[b].iata){ coords=mesAirportsCoords[b].coords; break; } }else{ if(codeActor==mesAirportsCoords[b].icao){ coords=mesAirportsCoords[b].coords; break; } } } if(coords){ // On a trouvé les coords de l'aéroport ! Remplacer dans mesActors mesActors[a].coords=coords; mesActors[a].draw(); } } } //if(codeType) //window.alert('Résolution des actorsAvecAirportSansCoords terminée.'); } function drawAreaFromFile(urlRequestStatus){ if(!urlRequestStatus.success) { nombreFichiersAreaNonCharges++; alert('drawAreaFromFile : Impossible de charger le fichier de régions !'); return(false); } var msg=urlRequestStatus.content; var externNode = parseXML(msg,svgDocu); if(externNode.firstChild){ nombreFichiersAreaCharges++; var mesAreas=externNode.firstChild.getElementsByTagName('area:Area'); // Toutes les lignes de coordonnees for(var a=0; a<mesAreas.length; a++){ //alert(a+') '+mesAreas.item(a).getElementsByTagName('area:name').item(0).firstChild.nodeValue); // Le title de la zone zoneTitle=mesAreas.item(a).getElementsByTagName('area:name'); if(zoneTitle.length) zoneTitle=zoneTitle.item(0).firstChild.nodeValue; else zoneTitle='not set' // Nouvelle Area --> nouveau SVGGElement var ng=svgDocu.createElement('g'); mesSubAreas=mesAreas.item(a).getElementsByTagName('area:SubArea'); if(mesSubAreas.length){ //alert(mesSubAreas.length+' subAreas'); for(var b=0; b<mesSubAreas.length; b++){ if(mesSubAreas.item(b).getElementsByTagName('rdfs:seeAlso').length){ subFile=mesSubAreas.item(b).getElementsByTagName('rdfs:seeAlso').item(0).getAttribute('rdf:resource'); if(subFile){ //alert(b+') '+subFile); getURL('outlines/'+subFile,drawAreaFromFile) } } } } mesOutlines=mesAreas.item(a).getElementsByTagName('area:points'); for(var b=0; b<mesOutlines.length; b++){ points=mesOutlines.item(b).firstChild.nodeValue; // On met tout de la forme "45.3;24.6;34.6"... points=points.trim(); // On supprime les retours à la ligne points=points.replace(/\n+/g,' '); // On comprime les mutiples espaces points=points.replace(/ +/g,';'); arrayPoints=points.split(';'); //alert(arrayPoints.length+' points'); // On détermine quel sera le 'path' issu du fichier pathString='M '; // Système pour avoir à tracer moins de points cpt=0; /* if(arrayPoints.length/2>100000) precision=5000; else if(arrayPoints.length/2>10000) precision=500; else if(arrayPoints.length/2>1000) precision=50; else if(arrayPoints.length/2>100) precision=5; else precision=1; */ for(var c=0; c<arrayPoints.length; c++){ if(c%2){ // Moins de points //if(cpt%precision==1) pathString+=latitudeToSVGCoordinatesMercator(arrayPoints[c])+' L '; }else{ // Moins de points cpt++; //if(cpt%precision==1) pathString+=longitudeToSVGCoordinatesMercator(arrayPoints[c])+' '; } } // On retire le trailing 'L ' et on met 'Z' à la place pour finir le 'd' pathString=pathString.substr(0,pathString.length-2); pathString+='Z'; //alert('Nouveau pathstring pour '+zoneTitle+' ('+pathString.length+' cara)\n'+pathString); var nti=svgDocu.createElement('title'); var nt=svgDocu.createTextNode(zoneTitle); nti.appendChild(nt); var np=svgDocu.createElement('path'); // Des couleurs différentes pour les régions var randomLayout=(parseInt(Math.random()*5)+1) //np.setAttribute('class','countryOutlines'); np.setAttribute('class','countryOutline'+randomLayout); np.setAttribute('d',pathString); ng.appendChild(np); ng.appendChild(nti); svgDocu.getElementById('world_outlines').appendChild(ng); } } } else{ nombreFichiersAreaNonCharges++; alert('drawAreaFromFile : Un fichier qui sert à rien ?\n'+msg); } } function addArea(mesAreas){ } function drawAirportsFromFile(urlRequestStatus){ // Charge en mémoire (array) les informations sur les aéroports. // Parcourt le fichier et dessine les aéroports sur la carte du monde. if(!urlRequestStatus.success) { alert('Impossible de charger le fichier des aéroports !'); return(false); } var msg=urlRequestStatus.content; //alert('File loaded : '+msg.substr(0,8)+'...'); var externNode = parseXML(msg,svgDocu); // Marche pour airports //alert('n aero : '+externNode.firstChild.nextSibling.getElementsByTagName('apt:Airport').length); // Marche pour airports-test //alert('n aero : '+externNode.firstChild.getElementsByTagName('apt:Airport').length); try{ // A marché (pour airports.rdf) var myAirports=externNode.firstChild.nextSibling.getElementsByTagName('apt:Airport'); } catch(erreur){ // Marche s'il n'y a pas de commentaire <!- -> avant le <rdf:RDF> var myAirports=externNode.firstChild.getElementsByTagName('apt:Airport'); } var latitude,longitude,apt,aptName,aptCoords; for(var a=0; a<myAirports.length; a++){ //alert('n°'+a+' : '+myAirports.getElementsByTagName('apt:latitude').item(0)); if(myAirports.item(a).getElementsByTagName('apt:latitude').length){ latitude=myAirports.item(a).getElementsByTagName('apt:latitude').item(0).firstChild.nodeValue; longitude=myAirports.item(a).getElementsByTagName('apt:longitude').item(0).firstChild.nodeValue; aptName=myAirports.item(a).getElementsByTagName('apt:name').item(0).firstChild.nodeValue; //alert('longitude='+longitude+'\nlatitude='+latitude); latitude=transformMinutesCoordsToDecimalCoords(latitude); longitude=transformMinutesCoordsToDecimalCoords(longitude); aptCoords=new Coords(latitude,longitude); if(myAirports.item(a).getElementsByTagName('apt:iata').length){ //apt=new Airport(aptName,aptCoords,'airportIata'); iata=myAirports.item(a).getElementsByTagName('apt:iata').item(0).firstChild.nodeValue; icao=myAirports.item(a).getElementsByTagName('apt:icao').item(0).firstChild.nodeValue; }else{ //apt=new Airport(aptName,aptCoords,'airportIcao'); iata=null; icao=myAirports.item(a).getElementsByTagName('apt:icao').item(0).firstChild.nodeValue; } // On ajoute ce qu'on sait dans l'Array //mesAirportsCoords.push(iata,icao,aptCoords); apt=new Airport(aptName,aptCoords,iata,icao); mesAirportsCoords.push(apt); //alert('new apt \n'+apt.coords+'\nlongitude='+longitude+'\nlatitude='+latitude); apt.draw(); //return(true); } } } function afficheInfosAirport(code){ var scale=svgDocu.documentElement.getCurrentScale(); // On retrouve le nom var name=getAirportName(code); if(!name) name='Code '+code; svgDocu.getElementById('airportName').firstChild.nodeValue=name; // On retrouve les coords var coords=getAirportCoords(code); if(coords){ var ax=longitudeToSVGCoordinatesMercator(coords.lon); var ay=latitudeToSVGCoordinatesMercator(coords.lat); } svgDocu.getElementById('airportName').setAttribute('x',ax+(5/scale)); svgDocu.getElementById('airportName').setAttribute('y',ay+(4/scale)); } function test(){ alert('Test!'); } function rien(){ return(true); } function afficheStatsChargement(){ alert('Statistiques de chargement :\n==========================\n\ Fichiers FOAF chargés :\t'+nombreFichiersFoafCharges+'\nFichiers FOAF non chargés :\t'+nombreFichiersFoafNonCharges+'\ \nFichiers de pays chargés :\t'+nombreFichiersAreaCharges+'\nFichiers de pays non chargés :\t'+nombreFichiersAreaNonCharges+'\ \nCoordonnées d\'aéroports demandées :\t'+nombreAirportCoordsExternesRecus+'\nCoordonnées d\'aéroports reçues :\t'+nombreAirportCoordsExternesRecus); } Coords.prototype.proximityTest=function(){ // État du script svgDocu.getElementById('texteTravailEnCours').firstChild.nodeValue='Test en cours...'; // Prendre ma position (inclusion dans différentes zones) // Le geoArea d'un acteur donné, à qui je me comparerai var otherGeoArea; // Le nom de la zone commune ? var fgeoarea=''; // Le résultat (un array d'arrays) var result=new Array(); // Initialisation proximityResults=Array(); // Premièrement, on fixe les positions de tous les acteurs possibles resolveActorsAvecAirportSansCoords(); var myGeoArea=this.getGeoArea(); //alert('proximityTest commence, pour mon clic = \n'+this.toString()+'\ndans la zone : '+myGeoArea); if(!myGeoArea){ window.alert('Impossible de poursuivre : votre position d\'origine n\'est pas connue ou pas définie !'); return(false); } // Prendre toutes les autres positions des gens var arrayActors=new Array(); for(var a=0; a<mesActors.length; a++){ // Réinitialisation des anciennes infos de zones (nouvel acteur) var myZone='Autres'; fgeoArea=''; //alert('proxTest : acteur suivant à tester : '+mesActors.item(a).name+' ('+a+'/'+mesActors.length+')'); if(mesActors.item(a).coords && mesActors.item(a).coords.lat){ // Maintenant on rapatrie les geoAreas et on cherche les similitudes otherGeoArea=mesActors.item(a).getGeoArea(); // État du script actualiseCompteurFichiersCharges(a,mesActors.length); svgDocu.getElementById('texteTravailEnCours').firstChild.nodeValue='Test en cours ('+(a+1)+'/'+(mesActors.length+1)+')'; //if(otherGeoArea.length) //alert('proxTest : GeoArea trouvée pour l\'acteur '+mesActors.item(a).name+' : \n'+otherGeoArea); // Attention : myGeoArea est un array d'arrays // (un array de Continent > Pays > Zone1 > Zone2) for(b=0; b<myGeoArea.length; b++){ // (et dans le sens inverse du tableau : de + en + précis) for(c=myGeoArea[b].length-1; c>=0; c--){ // Pour chaque zone de l'acteur testé, // on compare 2 à 2 avec mes zones à moi for(d=0; d<otherGeoArea.length; d++){ // Attention, otherGeoArea est aussi un array d'arrays for(e=0; e<otherGeoArea.length; e++){ //alert('on a '+otherGeoArea[e].length+' zones a comparer'); //fgeoArea='non defini'; for(f=0; f<otherGeoArea[e].length; f++){ //alert('on compare '+otherGeoArea[e][f]+' et '+myGeoArea[b][c]); if(otherGeoArea[e][f]==myGeoArea[b][c]){ // Même zone ! fgeoArea=myGeoArea[b][c]; //alert('vous et l\'acteur '+mesActors.item(a).name+' êtes dans une même zone\net son title est : '+myGeoArea[b][c]); // Retrouver l'element à partir du title... // On teste tous les <title> de world_map myZone='Autres'; var lesTitles=svgDocu.getElementById('world_map').getElementsByTagName('title'); for(g=0; g<lesTitles.length; g++){ //alert(g+'. nouveau title : '+lesTitles.item(g).firstChild.nodeValue); if(lesTitles.item(g).firstChild.nodeValue==myGeoArea[b][c]){ // On l'a trouvé myZone=lesTitles.item(g).parentNode.getElementsByTagName('zoneType').item(0).firstChild.nodeValue; //alert('donc la zone est '+myZone); break; } } //alert('meme zone et c\'est du type : '+myZone); } } } } } } //if(fresult){ if(fgeoArea){ try{ //alert('Vous êtes dans le même '+myZone.toLowerCase()+' que '+mesActors.item(a).name+' ('+fgeoArea+')'); proximityResults.push(mesActors.item(a).name,fgeoArea,myZone.toLowerCase()); }catch(erreur){ //alert('Vous êtes dans le même '+myZone.toLowerCase()+' que '+mesActors.item(a).name+' (erreur : '+erreur+')'); proximityResults.push(mesActors.item(a).name,'--Erreur--',myZone.toLowerCase()); } } } /* else{ alert('on ne cree pas cette personne sans coordonnees !'); alert(mesActors.item(a)); } */ } // État du script svgDocu.getElementById('texteTravailEnCours').firstChild.nodeValue='Test terminé.'; actualiseCompteurFichiersCharges(1,1); //alert('fin proxtest...\nlength='+proximityResults.length); var showProximityResults=''; for(var a=0; a<proximityResults.length; a+=3){ showProximityResults+=' '+proximityResults[a]+'\t'+proximityResults[a+1]+'\t'+proximityResults[a+2]+'\n'; //alert(proximityResults[a]); } formateResultsEnRDF(proximityResults); alert('Résultats de proximityTest() :\n===================\n'+showProximityResults); } function formateResultsEnRDF(arrayResults){ // On efface les anciens résultats et on recommence svgDocu.getElementById('results').removeChild(svgDocu.getElementById('scriptResults')); //var txtr=svgDocu.getElementById('scriptResults'); var txtr=svgDocu.createElement('text'); txtr.setAttribute('id','scriptResults'); var yLigne=15; var interligne=12; ntspan=svgDocu.createElement('tspan'); ntspan.setAttribute('x','5'); ntspan.setAttribute('y',yLigne); ntspan.appendChild(svgDocu.createTextNode('<rdf:RDF>')); txtr.appendChild(ntspan); yLigne+=interligne; yLigne+=interligne; ntspan=svgDocu.createElement('tspan'); ntspan.setAttribute('x','5'); ntspan.setAttribute('y',yLigne); ntspan.appendChild(svgDocu.createTextNode(' <!-- Situation des personnes par rapport a votre position actuelle -->')); txtr.appendChild(ntspan); for(var a=0; a<arrayResults.length; a+=3){ // Pour chaque nouveau <tspan>, une nouvelle ligne yLigne+=interligne; yLigne+=interligne; ntspan=svgDocu.createElement('tspan'); ntspan.setAttribute('x','5'); ntspan.setAttribute('y',yLigne); ntspan.appendChild(svgDocu.createTextNode(' <Person>')); txtr.appendChild(ntspan); yLigne+=interligne; ntspan=svgDocu.createElement('tspan'); ntspan.setAttribute('x','5'); ntspan.setAttribute('y',yLigne); ntspan.appendChild(svgDocu.createTextNode(' <name>'+arrayResults[a]+'</name>')); txtr.appendChild(ntspan); yLigne+=interligne; ntspan=svgDocu.createElement('tspan'); ntspan.setAttribute('x','5'); ntspan.setAttribute('y',yLigne); ntspan.appendChild(svgDocu.createTextNode(' <sameZoneType xml:lang="fr">'+arrayResults[a+2]+'</sameZoneType>')); txtr.appendChild(ntspan); yLigne+=interligne; ntspan=svgDocu.createElement('tspan'); ntspan.setAttribute('x','5'); ntspan.setAttribute('y',yLigne); ntspan.appendChild(svgDocu.createTextNode(' <sameZoneName xml:lang="fr">'+arrayResults[a+1]+'</sameZoneName>')); txtr.appendChild(ntspan); yLigne+=interligne; ntspan=svgDocu.createElement('tspan'); ntspan.setAttribute('x','5'); ntspan.setAttribute('y',yLigne); ntspan.appendChild(svgDocu.createTextNode(' </Person>')); txtr.appendChild(ntspan); } yLigne+=interligne; ntspan=svgDocu.createElement('tspan'); ntspan.setAttribute('x','5'); ntspan.setAttribute('y',yLigne); ntspan.appendChild(svgDocu.createTextNode('</rdf:RDF>')); txtr.appendChild(ntspan); svgDocu.getElementById('results').appendChild(txtr); } function Airport(name,coords,iata,icao){ // Constructeur de position géographique this.name=name; if(coords) this.coords=coords; else this.coords=''; this.iata=iata; this.icao=icao; } Object.prototype.isInArray=function(arr){ // (fr) Vérifie si un Object est contenu dans un tableau d'Objects //alert('dans Object.prototype.isInArray\n---\nThis : '+this+'\nLength : '+arr.length+'\n---\nArray : '+arr); var unique=true; for(var a=0; a<arr.length; a++){ //alert('on compare '+this+' et '+arr[a]); if(this==arr[a]){ //alert('Object.prototype.isInArray : trouvé à la position '+a); unique=false; break; } } if(unique) return(-1); else return(a); } Object.prototype.actorIsInArray=function(arr){ // (fr) Vérifie si un acteur semble contenu dans un tableau d'autres acteurs // en fonction de son nom et son adresse mail //alert('dans Object.prototype.isInArray\n---\nThis : '+this+'\nLength : '+arr.length+'\n---\nArray : '+arr); var unique=true; var mailboxToLookFor=this.mbox; var mailboxInArray; if(mailboxToLookFor.indexOf('@')!=-1){ // Si ce n'est pas déjà fait, on crypte pour comparer mailboxToLookFor=hex_sha1(mailboxToLookFor); } for(var a=0; a<arr.length; a++){ mailboxInArray=arr[a].mbox; if(mailboxInArray.indexOf('@')!=-1){ // On crypte pour comparer mailboxInArray=hex_sha1(mailboxInArray); } //alert('on compare '+this.name+' et '+arr[a].name); if(this.name==arr[a].name || mailboxToLookFor==mailboxInArray){ //alert('Object.prototype.isInArray : trouvé à la position '+a); unique=false; break; } } if(unique) return(-1); else return(a); } Airport.prototype.draw=function(){ if(!this.coords || this.coords.lat==undefined){ //alert('pas de coords pour l\'aéroport '+this.name); return(false); } var ax=longitudeToSVGCoordinatesMercator(this.coords.lon); var ay=latitudeToSVGCoordinatesMercator(this.coords.lat); nc=svgDocu.createElement('circle'); nc.setAttribute('cx',ax); nc.setAttribute('cy',ay); nc.setAttribute('r',diametrePointsAirports); if(this.iata) nc.setAttribute('class','airportIata'); else nc.setAttribute('class','airportIcao'); // Affiche le nom quand on clique if(this.iata) nc.setAttribute('onmouseover','afficheInfosAirport(\''+this.iata+'\');afficheActorNamesAtAirport(\''+this.iata+'\')'); else nc.setAttribute('onmouseover','afficheInfosAirport(\''+this.icao+'\');afficheActorNamesAtAirport(\''+this.icao+'\')'); nc.setAttribute('onclick','locateMousePoint(evt)'); svgDocu.getElementById('carteAirports').appendChild(nc); } function Actor0(name,coords){ // Constructeur de personnes this.name=name; if(coords) this.coords=coords; else this.coords=''; } function Actor(name,mbox,coords,aptCode,photoUri,foafUri){ // Constructeur de personnes this.name=name.trim(); this.mbox=mbox.trim(); this.aptCode=aptCode.trim(); this.photoUri=photoUri.trim(); this.foafUri=foafUri.trim(); if(coords) this.coords=coords; else this.coords=''; } function Coords(lat,lon,alt){ // Constructeur de positions géographiques this.lat=lat; this.lon=lon; this.alt=alt; } Array.prototype.item=function(n){ if(n>=this.length) alert('Cet élément n\'existe pas : item('+n+')'); else return this[n]; } Array.prototype.toString=function(){ result=new String('Array('+this.length+'){'); for(a=0; a<this.length; a++){ result+=this[a]; if(a!=this.length-1 && this.length>1) result+=','; } result+='}'; return result; } Array.prototype.afficheAvecVirgules=function(){ return this.join(', '); } Coords.prototype.toString=function(){ // Formatage des coordonnées (pour affichage dans un alert box) return '===COORDS======\nLatitude : '+this.lat+'\nLongitude : '+this.lon+'\nAltitude : '+this.alt; } Actor.prototype.toString=function(){ // Formatage des coordonnées (pour affichage dans un alert box) return '===ACTEUR======\nNom : '+this.name+'\nMail : '+this.mbox+'\nLatitude : '+this.coords.lat+'\nLongitude : '+this.coords.lon+'\nAltitude : '+this.coords.alt; } Coords.prototype.draw=function(){ var ax=longitudeToSVGCoordinatesMercator(this.lon); var ay=latitudeToSVGCoordinatesMercator(this.lat); nc=svgDocu.createElement('circle'); nc.setAttribute('fill','red'); nc.setAttribute('cx',ax); nc.setAttribute('cy',ay); nc.setAttribute('r','4'); svgDocu.getElementById('dessins').appendChild(nc); } Actor.prototype.draw=function(){ if(this.coords){ //return this.coords.draw(); var ax=longitudeToSVGCoordinatesMercator(this.coords.lon); var ay=latitudeToSVGCoordinatesMercator(this.coords.lat); nc=svgDocu.createElement('circle'); nc.setAttribute('class','actor'); nc.setAttribute('cx',ax); nc.setAttribute('cy',ay); nc.setAttribute('r',diametrePointsActors); //Oui mais... un acteur en cache un autre ? nc.setAttribute('onclick','alert(\''+this.name+'\')'); svgDocu.getElementById('carteActors').appendChild(nc); }else alert('Impossible de dessiner l\'acteur : pas de coordonnées.'); } Coords.prototype.getGeoArea=function(){ var ay=latitudeToSVGCoordinatesMercator(this.lat); var ax=longitudeToSVGCoordinatesMercator(this.lon); //alert('getGeoArea\ngoto locatePoint pour les points SVG '+ax+' et '+ay); return locatePoint(ax,ay); } Actor.prototype.getGeoArea=function(){ //alert('on getGeoArea des coords d\'un acteur...\n'+this.name); return this.coords.getGeoArea(); } function locateCoords(coords){ alert('on locateCoords '+coords.toString()); var ax=longitudeToSVGCoordinatesMercator(this.lon); var ay=latitudeToSVGCoordinatesMercator(this.lat); return locatePoint(ax,ay); } Coords.prototype.locateCoords=function(){ alert('on locateCoords '+this.toString()); var ax=longitudeToSVGCoordinatesMercator(this.lon); var ay=latitudeToSVGCoordinatesMercator(this.lat); return locatePoint(ax,ay); } function transformMinutesCoordsToDecimalCoords(coord){ // Transforme 49-01N en 49.16667 // Attention, il y a aussi 49-01-24N ! // Ne marche plus avec le MSIE JS parser //var lettre=coord.substr(-1); // Donc : var lettre=coord.substr(coord.length-1,1); var debut=coord.substr(0,coord.indexOf('-')); var fin=coord.substr(coord.indexOf('-')+1,coord.substr(coord.indexOf('-')+1).length-1); if(fin.indexOf('-')!=-1){ // Format 64-13-19W --> 64-1319W //alert('un - dans fin : '+fin+'\n'+fin.indexOf('-')); fin=fin.substr(0,fin.indexOf('-'))+fin.substr(fin.indexOf('-')+1); } var deccoord=Math.round(debut)+'.'+Math.round(fin*10000*(10/6)); if(lettre=='S' || lettre=='W'){ deccoord=-deccoord; } //alert('Deb '+debut+'\nFin '+fin+'\nLet '+lettre+'\nDec '+deccoord+'\nlettre '+lettre) return(deccoord); } function getActorCoordsById(actorId){ return getActorCoords(svgDocu.getElementById(actorId)); } function getActorsByName(name){ name=name.toLowerCase(); var arrayActors=new Array(); var tmp; var myActors=svgDocu.getElementsByTagName('acteur'); for(var a=0; a<myActors.length; a++){ if(myActors.item(a).getElementsByTagName('name')){ nameLoop=myActors.item(a).getElementsByTagName('name').item(0).firstChild.nodeValue().toLowerCase(); if(name==nameLoop){ tmp=new Actor(name,getActorCoords(myActors.item(a))); arrayActors.push(tmp); } } } return arrayActors; } function getActorCoords(actor){ if(actor.getElementsByTagName('location')) { // On cherche les coords, et l'aéroport à défaut... if(actor.getElementsByTagName('location').item(0).getElementsByTagName('coords').length) { var lat=actor.getElementsByTagName('location').item(0).getElementsByTagName('coords').item(0).getElementsByTagName('lat').item(0).firstChild.nodeValue(); var lon=actor.getElementsByTagName('location').item(0).getElementsByTagName('coords').item(0).getElementsByTagName('lon').item(0).firstChild.nodeValue(); return new Coords(lat,lon); } else if(actor.getElementsByTagName('location').item(0).getElementsByTagName('nearestAirport').length) { var code=actor.getElementsByTagName('location').item(0).getElementsByTagName('nearestAirport').item(0).firstChild.nodeValue(); return(getAirportCoords(code)); } } return false; } function latitudeToSVGCoordinatesMercator(lat){ // Rappel : il ne faut pas de '°' -- c'est un float // Si il y a un S ou un W (ça peut arriver) on met le signe 'moins' if(lat==undefined){ //alert('undefined, break!'); return(false); } try{ // Ne marche plus pour MSIE JS parser //var lettre=lat.substr(-1); var lettre=lat.substr(lat.length-1,1); }catch(erreur){ var lettre=null; //alert('Erreur '+erreur+' pour lat='+lat); } if(lettre=='N'){ lettre='Nord'; //alert('Donc la latitude doit etre '+lat.substr(0,lat.length-1)); // On supprime la lettre de fin lat=lat.substr(0,lat.length-1); }else if(lettre=='S'){ lettre='Sud'; //alert('Donc la latitude doit etre '+lat.substr(0,-1)+'\n ou '+lat.substr(0,lat.strlen-1)+'\n ou '+lat.substring(0,-1)); // On supprime la lettre de fin et on prend l'opposé lat=-lat.substr(0,lat.length-1); }else{ lettre=null; } if(isNaN(lat)) alert('latitudeToSVGCoordinatesMercator : on transforme '+lat+' en une coordonnée SVG \nLettre : '+lettre+'\nlat.length='+lat.length); return (mapHeight/2)-(mapHeight)*(lat/180); } function longitudeToSVGCoordinatesMercator(lon){ // Il semble qu'il y ait des problèmes avec les substringuages de nombres négatifs try{ //var lettre=lon.substr(-1); //var lettre=lat.substr(-1); var lettre=lon.substr(lon.length-1,1); //var lettre=lon.substring(-1); }catch(erreur){ // Ca arrive quand lon=-0.45 par exemple var lettre=null; //alert('Erreur '+erreur+' pour lon='+lon); } // Si il y a un S ou un W (ça peut arriver) on met le signe 'moins' if(lettre=='E'){ lettre='East'; //alert(lettre+' - Donc la longitude doit etre '+lon.substr(0,lon.length-1)); // On supprime la lettre de fin lon=lon.substr(0,lon.length-1); }else if(lettre=='W'){ lettre='West'; //alert(lettre+' - Donc la longitude doit etre '+lon.substr(0,-1)+'\n ou '+lon.substr(0,lon.strlen-1)+'\n ou '+lon.substring(0,-1)); // On supprime la lettre de fin et on prend l'opposé lon=-lon.substr(0,lon.length-1); }else{ lettre=null; } //if(lettre) //alert('longitudeToSVGCoordinatesMercator : Il y a une lettre.\nOn transforme '+lon+' en une coordonnée SVG \nLettre : '+lettre); return (mapWidth/2)+(mapWidth)*(lon/360); } function SVGCoordinatesToLatitudeMercator(y){ var lat=-(y/(mapHeight/2)-1)*90; if(lat<0) var lettre="S"; else var lettre="N"; return(Math.abs(Math.round(lat*10000)/10000)+lettre); } function SVGCoordinatesToLongitudeMercator(x){ // hmm var lon=-(x/(mapWidth/2)-1)*90; var lon=-(x/(mapWidth/2)-1)*180; if(lon<0){ var lettre="E"; // je m'a gourré //var lettre="W"; //alert('SVGCoordinatesToLongitudeMercator : C\'est à l\'ouest ; x='+x); }else{ var lettre="W"; } return(Math.abs(Math.round(lon*10000)/10000)+lettre); } function locateMousePoint(evt){ // (fr) Calculer les coordonnées de la souris // (en) Get the cursor's coordinates var svgDocu=evt.getTarget().getOwnerDocument(); var svgDocEl=svgDocu.getDocumentElement(); var scale=svgDocEl.getCurrentScale(); var trans=svgDocEl.getCurrentTranslate(); var x=evt.getClientX(); var y=evt.getClientY(); var nx=x/scale+((0.0-trans.x)/scale); var ny=y/scale+((0.0-trans.y)/scale); // je ne m'en sers plus //svgDocu.getElementById('position').firstChild.nodeValue='Détermination en cours...'; svgDocu.getElementById('yourCurrentLocationName').firstChild.nodeValue='Détermination en cours...'; // Et on s'en vante lastClickedCoords=new Coords(SVGCoordinatesToLatitudeMercator(ny),SVGCoordinatesToLongitudeMercator(nx)); //alert('Coords locatemousepoint : '+lastClickedCoords+'\na partir de '+nx+','+ny+'\n(nx doit etre bon, pas lon)'); var texteArea=locatePoint(nx,ny); // Copier-coller if(texteArea){ var texte=''; for(var a=0; a<texteArea.length; a++){ texte+=texteArea[a].afficheAvecVirgules(); if(a<texteArea.length-1) texte+=' ou '; } } else { var texte='Aucune'; } svgDocu.getElementById('yourCurrentLocationName').firstChild.nodeValue=texte; afficheLastClickedCoords(); return texteArea; } function locatePoint(nx,ny){ // (fr) Découvrir la région à partir d'un point (x,y) en coordonnées 'SVG' // (en) Discover the region from a (x,y) point //alert('locatePoint pour '+nx+','+ny); if(isNaN(nx) || isNaN(ny)){ alert('locatePoint : mauvais chiffres : '+nx+','+ny); return(false); } var arrayFoundTitles=testEachGroup(svgDocu.getElementById('world_outlines'),new Array(),nx,ny); //arrayFoundTitles.push('pouet'); //alert('locatepoint arrayfoundtitles='+arrayFoundTitles); // (fr) On teste si un title n'est pas deja contenu dans un autre title plus précis ; si oui, on l'efface. // (en) Test if a title isn't already contained into another more precise title ; if yes, drop it. // (Ex : 'Europe' && 'Europe>France' => 'Europe>France'). // on les compare 2 à 2 for(var a=0; a<arrayFoundTitles.length; a++){ // Test chaque position complete possible (France, Europe en est une...) //alert('nouvelle boucle avec '+arrayFoundTitles[a]); for(var b=0; b<arrayFoundTitles.length; b++){ // Teste d'abord France, ensuite Europe... if(a==b || arrayFoundTitles[a]=='--' || arrayFoundTitles[a]=='') break; sousChaine1=arrayFoundTitles[a].join(', '); sousChaine2=arrayFoundTitles[b].join(', '); //alert('on va tenter de trouver '+sousChaine1+' et le comparer a '+sousChaine2); if(sousChaine1.substr(sousChaine1.length-sousChaine2.length)==sousChaine2){ //alert(sousChaine2+' est contenu dans '+sousChaine1); arrayFoundTitles[b]=new String('--'); } } } // (fr) On construit un résultat propre à afficher à l'utilisateur // (en) Reconstruction of a clean result for human display var foundTitlesFinal=new Array(); var afficheArrays=''; for(var a=0; a<arrayFoundTitles.length; a++) { if(arrayFoundTitles[a]!='--'){ afficheArrays+='['+a+'] '+arrayFoundTitles[a]+'\n'; foundTitlesFinal.push(arrayFoundTitles[a]); } } if(afficheArrays){ //alert('Résultat de la résolution : \n'+afficheArrays); var texte=''; for(var a=0; a<foundTitlesFinal.length; a++){ texte+=foundTitlesFinal[a].afficheAvecVirgules(); if(a<foundTitlesFinal.length-1) texte+=' ou '; } } else { var texte='Aucune'; } // (fr) Retourne un array de positions possibles (sur un même pixel, on peut être en espagne ET en france...) return foundTitlesFinal; } function testEachGroup(fromId,foundTitles,nx,ny){ // (fr) Teste tous les éléments 'g' pour savoir si le point choisi est contenu dans ces groupes, // et renvoie le texte 'title' associé var newFoundTitle; //alert('on commence avec '+fromId+'\nid : '+fromId.id); //alert('qui a enfants '+fromId.childNodes); // (fr) Pour JScript, childNodes() marche ; pas pour Adobe où il faut remplacer par childNodes. for(var a=0; a<fromId.childNodes.length; a++){ // (en) If it's a path: test if our point is inside it // If it's a g: call the function recursively // If no other children: stop //alert(fromId.childNodes.item(a)); if(fromId.childNodes.item(a).tagName=='path'){ //alert('c est un path'); // On utilise les bounding boxes pour éliminer les pays dont on est sûr qu'ils ne sont pas sous la souris if(nx < fromId.childNodes.item(a).getBBox().x || nx > (fromId.childNodes.item(a).getBBox().x + fromId.childNodes.item(a).getBBox().width) || ny < (fromId.childNodes.item(a).getBBox().y) || ny > (fromId.childNodes.item(a).getBBox().y + fromId.childNodes.item(a).getBBox().height)) { // On est en-dehors des bounding-boxes } else { // On est dans les bounding-boxes, donc on lance le test if(isInsidePath(nx,ny,fromId.childNodes.item(a))){ //alert('trouve dans '+fromId.childNodes.item(a).getAttribute('id')) newFoundTitle=getAllTitlesFor(fromId.childNodes.item(a),new Array()); foundTitles.push(newFoundTitle); //alert('Position 1 trouvee : '+newFoundTitle); } } } else if(fromId.childNodes.item(a).tagName=='g'){ //alert('c est un g'); // (en) It's a 'g' element -> Try to find a title recursively testEachGroup(fromId.childNodes.item(a),foundTitles,nx,ny); } } return(foundTitles); } // === Ceci est plutôt géométrique ======================================== function getAllTitlesFor(pathHandle,arrayTitles){ // (en) Get all the parent elements' 'title' values, for a given id //alert(' --> recherche des titres pour '+pathHandle.id+' ('+arrayTitles+')'); // (en) Exit when we meet the root element if(pathHandle.getAttribute('id')=='world_outlines'){ return(arrayTitles); } if(pathHandle.getElementsByTagName('title').length){ //alert('** il y a un title : '+pathHandle.getElementsByTagName('title').item(0).firstChild.nodeValue+'\nLe parent est : '+pathHandle.getElementsByTagName('title').item(0).parentNode.id+'\net on voudrait : '+pathHandle.id); // (en) If the n-level child element's parent matches pathHandle, then it is a 1-level child // (which is the correct position for a 'title' element) if(pathHandle==pathHandle.getElementsByTagName('title').item(0).parentNode){ //moreString=', '+pathHandle.getElementsByTagName('title').item(0).firstChild.nodeValue; arrayTitles.push(pathHandle.getElementsByTagName('title').item(0).firstChild.nodeValue); } //else... // (en) The child's parent doesn't match pathHandle... // then we're not dealing with the same 'generation' (we went too far in the DOM tree) // So: do nothing, loop } if(pathHandle.parentNode){ pathHandle=pathHandle.parentNode; return getAllTitlesFor(pathHandle,arrayTitles); } } function isInsidePath(x,y,path){ var pathm=path.getAttribute('d'); // (fr) Ne marche que pour les 'L' dans l'attribut 'd' des paths // (les courbes de Bézier, etc. pas encore fait, on ne le fera que si nécéssaire) // (en) Works only for 'L's inside path's 'd' attribute // (Bezier curves, etc. not yet done, I wonder if it will ever be, depends of how we use it) // (fr) Variables pour parcourir la chaine de caractères... // (en) String parsing variables... var compteur=0; var pointX; var pointY; var previousPointX="non";// (fr) Valeur par défaut quand le calcul n'est pas encore fait // (en) Default value when not yet computed var previousPointY; // (fr) Pour se souvenir du premier point // (en) Keep the first point in mind var firstPointX; var firstPointY; var nbIntersections=0; // (fr) On saute le M qu'on trouve au début du 'd' du path // (en) At the beginning of the path's 'd', there is always a M, which we will skip var remainingPath=pathm.substr(1,pathm.length).trim(); // (fr) Pour chaque extrémité, on cherche à savoir si le segment croise la ligne horizontale // virtuelle à droite de notre point initial (x,y) // (en) For each extremity, we will see if the segment crosses the virtual horizontal line // at right from our initial (x,y) point while(remainingPath.length && compteur<1000000){ // variable 'compteur' is just here to prevent the 'while' from looping eternally posFirstPoint=remainingPath.indexOf(' '); pointX=remainingPath.substr(0,posFirstPoint); posSecondPoint=remainingPath.indexOf('L'); // (en) At the end if(remainingPath.indexOf('L')==-1) posSecondPoint=remainingPath.indexOf('Z'); pointY=remainingPath.substr(posFirstPoint,posSecondPoint-posFirstPoint).trim(); remainingPath=remainingPath.substr(posSecondPoint+1,remainingPath.length).trim(); // (fr) Calcule s'il y a une intersection // (en) Compute if there is a crossing if(previousPointX!="non"){ if(lookForIntersection(x,y,pointX,pointY,previousPointX,previousPointY)) nbIntersections++; }else{ firstPointX=pointX; firstPointY=pointY; } compteur++; //window.alert('pointX : '+pointX+'\npointY : '+pointY+'\nremainingPath : '+remainingPath); previousPointX=pointX; previousPointY=pointY; } if(compteur>=999999){ alert('Il semble que isInsidePath ait fait plus de boucles que souhaité...\nremainingpath='+remainingPath); } // At the end, perform the test with the first parsed points if(lookForIntersection(x,y,pointX,pointY,firstPointX,firstPointY)) nbIntersections++; //window.alert('isinsidepath terminé\nNombre d\'intersections : '+nbIntersections+'\nNombre de calculs : '+compteur); if(nbIntersections%2!=1){ // Odd number of intersections => point not inside the path return false; } else { // Even number of intersections => point inside the path return true; } } function lookForIntersection(px,py,x1,y1,x2,y2){ var foundOne=false; var xIntersection; //alert('Intersection?\nx1 : '+x1+'\ny1 : '+y1+'\nx2 : '+x2+'\ny2 : '+y2); if(x1>=px || x2>=px){ if(x1>=px && x2>=px){ // (en) Case 1 : all 2 extremities of the segment are at point P's right side if(y1>=py && y2<py){ // Top to bottom foundOne=true; //window.alert('Oui ! 1-1'); } else if(y2>=py && y1<py){ // Bottom to top foundOne=true; //window.alert('Oui ! 1-2'); } //else window.alert('Non 1'); } else { // (en) Case 2 if(!((y1>py && y2>py) || (y1<py && y2<py))) { // (en) Find the x-coord of the segment when y = pointY. xIntersection=(1.0*x1+((py-y1)*(x2-x1)/(y2-y1))); if(xIntersection>px){ foundOne=true; //window.alert('Oui ! 2 '+xIntersection); } //else window.alert('Non ! 2 '+xIntersection); } //else window.alert('Non ! 3'); } } //else window.alert('Non ! 4'); return foundOne; } function traceOutlines(evt){ alert('attention ! Ne marche plus, normalement'); // (en) For each clic, append the coordinates of this point to the string defining the path's 'd' element var svgDocu=evt.getTarget().getOwnerDocument(); var svgDocEl=svgDocu.getDocumentElement(); var scale=svgDocEl.getCurrentScale(); var trans=svgDocEl.getCurrentTranslate(); var x=evt.getClientX(); var y=evt.getClientY(); // Coordonnées sur le graphe var nx=x/scale+((0.0-trans.x)/scale); var ny=y/scale+((0.0-trans.y)/scale); var newText=svgDocu.createTextNode(nx+' '+ny+' L '); svgDocu.getElementById('line1').appendChild(newText); // Coordonnées réelles var lat=SVGCoordinatesToLatitudeMercator(ny); var lon=SVGCoordinatesToLongitudeMercator(nx); var newText=svgDocu.createTextNode(lat+' '+lon+' '); svgDocu.getElementById('line3').appendChild(newText); } String.prototype.trim=function(){ // Create the prototype for trim() on the String object // Skip leading and trailing whitespace and return everything in between var x=this; x=x.replace(/^\s*(.*)/, "$1"); x=x.replace(/(.*?)\s*$/, "$1"); return x; } // === Fin du script ================================== ]]></script> </svg>
Mon fichier foaf.rdf personnel.
<?xml version="1.0" encoding="iso-8859-1"?> <rdf:RDF xmlns:wot="http://xmlns.com/wot/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:rss="http://purl.org/rss/1.0/" xmlns="http://xmlns.com/foaf/0.1/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:lang="http://purl.org/net/inkel/rdf/schemas/lang/1.1#" xmlns:wn="http://xmlns.com/wordnet/1.6/" xmlns:air="http://www.megginson.com/exp/ns/airports#" xmlns:contact="http://www.w3.org/2000/10/swap/pim/contact#" xmlns:dc="http://purl.org/dc/elements/1.1/"> <foaf:Person rdfs:id="cedric"> <foaf:name>Cédric Kiss</foaf:name> <foaf:title>Mr</foaf:title> <foaf:firstName>Cédric</foaf:firstName> <foaf:surname>Kiss</foaf:surname> <foaf:nick>Cédric</foaf:nick> <foaf:mbox_sha1sum>2da7e65b06d1b74f51c8d18a3c0b27cc360e2fe6</foaf:mbox_sha1sum> <foaf:homepage rdf:resource="http://ckiss.net/cedric/"/> <foaf:depiction rdf:resource="http://ckiss.net/copains/photos/photo_donindiano4.jpg"/> <foaf:phone rdf:resource="tel:06-73-69-68-84"/> <foaf:workplaceHomepage rdf:resource="http://www.w3.org/"/> <foaf:schoolHomepage rdf:resource="http://www.u-paris2.fr/html/formations/infocom/imac_inge.htm#ing"/> <contact:nearestAirport> <wn:Airport air:iata="NCE"/> </contact:nearestAirport> <foaf:knows> <foaf:Person> <foaf:mbox rdf:resource="mailto:charles@w3.org"/> <foaf:firstname>Charles</foaf:firstname> <foaf:familyname>McCathieNevile</foaf:familyname> </foaf:Person> </foaf:knows> <foaf:knows> <foaf:Person> <foaf:firstname>Karima</foaf:firstname> <foaf:familyname>Boudaoud</foaf:familyname> </foaf:Person> </foaf:knows> <foaf:knows> <foaf:Person> <foaf:mbox rdf:resource="mailto:caroline@w3.org"/> <foaf:firstname>Caroline</foaf:firstname> <foaf:familyname>Baron</foaf:familyname> </foaf:Person> </foaf:knows> <foaf:knows> <foaf:Person> <foaf:mbox rdf:resource="mailto:coralie@w3.org"/> <foaf:firstname>Coralie</foaf:firstname> <foaf:familyname>Mercier</foaf:familyname> </foaf:Person> </foaf:knows> <foaf:knows> <foaf:Person> <foaf:mbox rdf:resource="mailto:bert@w3.org"/> <foaf:firstname>Bert</foaf:firstname> <foaf:familyname>Bos</foaf:familyname> </foaf:Person> </foaf:knows> <foaf:knows> <foaf:Person> <foaf:mbox rdf:resource="mailto:carine@w3.org"/> <foaf:firstname>Carine</foaf:firstname> <foaf:familyname>Bournez</foaf:familyname> </foaf:Person> </foaf:knows> <foaf:knows> <foaf:Person> <foaf:mbox rdf:resource="mailto:ylafon@w3.org"/> <foaf:firstname>Yves</foaf:firstname> <foaf:familyname>Lafon</foaf:familyname> </foaf:Person> </foaf:knows> <foaf:knows> <foaf:Person> <foaf:mbox rdf:resource="mailto:alex@w3.org"/> <foaf:firstname>Alexandra</foaf:firstname> <foaf:familyname>Lavirotte</foaf:familyname> </foaf:Person> </foaf:knows> <foaf:knows> <foaf:Person> <foaf:mbox rdf:resource="mailto:danield@w3.org"/> <foaf:firstname>Daniel</foaf:firstname> <foaf:familyname>Dardailler</foaf:familyname> </foaf:Person> </foaf:knows> <foaf:knows> <foaf:Person> <foaf:mbox rdf:resource="mailto:rigo@w3.org"/> <foaf:firstname>Rigo</foaf:firstname> <foaf:familyname>Wenning</foaf:familyname> </foaf:Person> </foaf:knows> <lang:masters>fr</lang:masters> <lang:masters>en</lang:masters> </foaf:Person> </rdf:RDF>
Voici le mail envoyé à la liste www-rdf-interest.
Hi RDF enthusiasts,
As part of the SWAD-Europe project [1], I have been working with Charles McCathieNevile to provide a graphical interface to RDF location information for the RDF community.
The purpose is to determine if some people are located in the same "area" as you ("Alice is in the same state; Bob is in the same city"...) as you travel. This could be as acurate as you wish, but on the other hand you will have to build your own data sets (in RDF, hopefully, so that they could be re-useable).
The graphics are displayed in SVG, W3C's XML-based 2D vector format; the whole process is done client-side. RDF location information comes from the plethora of FOAF [2] files around the web, and can be described either with their nearestAirport or with real lat/long co-ordinates.
You can also restrict the number of persons, to better suit your needs. For example: you may only want to keep people whose interests involve 'Accessibility' (for that, you will need to make a minor edit to the source code).
Although it's still under development, the main idea is here. You can find files, source code, screenshots and other useful information about this project at:
http://www.w3.org/2001/sw/Europe/200306/geo/readme_carte_zones_monde_rdf.html
Cheers,
[1] http://www.w3.org/2001/sw/Europe - SWAD-Europe
[2] http://rdfweb.org/ - Friend of a Friend project
Cédric Kiss
___________________________________________________
SWAD-Europe - http://www.w3.org/2001/sw/Europe/
W3C - INRIA Sophia Antipolis, France
Voici la feuille de style XSL qui a servi à générer la table des matières à partir du fichier HTML (on peut certainement faire beaucoup mieux, mais c'est néanmoins utilisable) :
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <body> <h2>Sommaire :</h2> <ul> <xsl:apply-templates/> </ul> </body> </html> </xsl:template> <xsl:template match="div"> <xsl:apply-templates select="h2|h3|h4"/> </xsl:template> <xsl:template match="h2"> <li><b><xsl:value-of select="."/></b></li> </xsl:template> <xsl:template match="h3"> <ul> <li><xsl:value-of select="."/></li> </ul> </xsl:template> <xsl:template match="h4"> <ul><ul> <li><i><xsl:value-of select="."/></i></li> </ul></ul> </xsl:template> </xsl:stylesheet>
Voici l'écran qui apparaît une fois le script chargé :
Vue globale de l'affichage du script.
Cet affichage dépend du nombre du nombre d'aéroports, d'acteurs et de pays chargés.
Comme c'est un graphique SVG, on peut zoomer pour afficher plus de détails dans une région donnée. Lorsqu'on passe la souris sur un élément, s'affichent les informations sur l'aéroport et sur les acteurs présents.
Détail du script (zoom vur la France).