Comment récupérer la position (LatLng) d'une InfoWindow Google Maps ?
En utilisant InfoWindow.getPosition() me direz-vous. Mais cette méthode, pourtant bien présente dans la documentation officielle, ne marche pas (en tout cas chez moi, et visiblement pas que) : elle renvoie toujours null.
Ce problème a été remonté depuis Février 2011 à Google via un rapport de bug, mais en attendant qu'elle soit fixée, voici ma solution de contournement.
- Lier l'InfoWindow à un marker (même si l'InfoWindow apparait au-dessus d'un marker, elle n'y est pas lié par défaut)
- Récupérer la position du marker lié à l'InfoWindow grâce à Marker.getPosition()
Pour la première étape, on va ajouter ce lien au prototype InfoWindow :
(function () {
google.maps.InfoWindow.prototype.marker = null;
google.maps.InfoWindow.prototype.setMarker = function(marker) {
this.marker = marker;
};
google.maps.InfoWindow.prototype.getMarker = function() {
return this.marker;
};
})();
Pour ceux qui ne comprennent pas, on ajoute des méthodes à la classe InfoWindow de Google Maps. Il suffit de placer ce code une fois dans la page pour que cela fonctionne.
Donc, lors de la création (ou l'affichage) de notre InfoWindow, on va la lier au marker correspondant :
var
infowindow = new google.maps.InfoWindow();
infowindow.setMarker(marker);
Ensuite, pour la dernière étape, on récupère la position du marker :
var
position = infoWindow.getMarker().getPosition();
Cette question est mainte fois abordée sur le web, mais on trouve rarement une version satisfaisante. Alors pour les impatients qui sont tombés sur cette page après une recherche Google, voici directement le code :
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
}
;
Pour l'utiliser :
// Supprimer le premier élément du tableau
array.remove(0);
// Supprimer l'avant dernier élément du tableau
array.remove(-1);
Comme vous le remarquerez, c'est pompé directement d'ici. C'est à ce jour la meilleur version d'un code de suppression d'un tableau que j'ai pu trouver.
Le principe : on modifie le type Array (son prototype) afin de lui rajouter une méthode remove. Ensuite on peut appeler cette méthode sur n'importe quel tableau Javascript.
Les avantages (pas rapport aux autres méthodes) : c'est clean (méthode ajoutée au type Array), complet (la suppression de l'élément du tableau va bien décaler tous les éléments suivants) et puissant (possibilité de supprimer l'avant dernier élément par exemple).
N'hésitez pas à aller consulter l'article original pour comprendre le détail du code de la méthode remove.
Bonjour à tous,
Je vous présente aujourd'hui un outil que j'ai développé en HTML5 + Javascript, utilisant Google Maps, et open source : la calculette carbone voyage.
L'objectif est de vulgariser au maximum la notion d'empreinte carbone pour les transports. La transparence sur les calculs est complète, les sources sont disponibles sur github, et les détails des calculs sont publics.
C'est un peu dommage que le site devienne disponible à la fin des vacances, mais les projets perso prennent toujours un peu de temps :).
N'hésitez pas à faire des retours dans les commentaires.

Je viens de recevoir un mail de mon hébergeur, Celeonet, m'informant d'une attaque sur leurs infrastructure.
C'est sur qu'à lire leur blog, ça parait pas grand chose :
Consécutivement à ce piratage, une liste d’identifiants utilisateurs Celeonet a été dévoilée et a pu être librement consultée.
Le fait qu’une liste d’identifiants utilisateurs ait été
dévoilée ne met en aucun cas en danger les comptes et les sites
rattachés.
Super, mais alors pourquoi dans la foulée je reçois un mail qui m'explique que tous mes mots de passe ont été changés immédiatement ?
Je pense que ça aurait été utile de le préciser sur leur blog, au lieu de jouer à "tout va bien", et "c'est la faute du webmaster, pas de l'hébergeur".
Surtout qu'on a pas le droit à un mot d'excuse, pas plus d'explications, est-ce qu'il est nécessaire de modifier nos mots de passe mail par exemple, y'a t'il des conséquences sur nos sites à nous... Si il a été nécessaire de modifier tous les mots de passe de tous les clients, on peut s'attendre à une meilleure communication que ça !
Le plus drôle dans cette histoire, c'était que tout ça était conséquence d'une attaque sur le site de Marine Le Pen.
Merci Celeonet.
Bonjour à tous,
Si vous aussi vous travaillez avec Google Maps v3, et que vous avez besoin par exemple de rafraichir les marqueurs qui se trouvent sur la carte lorsqu'on zoom ou on se déplace, vous avez peut être remarqué que la doc conseille d'utiliser l'évènement "bounds_changed".
Seulement cet évènement est déclenché en continu quand on déplace la carte. On se retrouve donc avec une quantité énorme de requêtes sur le serveur (et rafraichir les marqueurs de la carte plusieurs fois par seconde, ça n'a pas trop d'intérêt).
Bref, après que plusieurs personnes aient râlé, Google a proposé un bugfix sous la forme de l'évènement "idle". Cet évènement est déclenché après un certain temps sans action de l'utilisateur. Pratique, mais j'aurais quand même préféré un simple évènement qui se déclenche quand l'utilisateur fini de déplacer la carte (un mouseUp).
Voici tout simplement comment l'utiliser :
google.maps.event.addListener(map, 'idle', function() {
});
Ils devraient quand même le préciser dans la doc, car la solution se trouve dans le rapport de bug de google :
http://code.google.com/p/gmaps-api-issues/issues/detail?id=1371
Petite présentation d'un plugin développé par un ami, pour la dernière version de PowerPoint (du pack Office 2010), il s'agit d'AutoSummary.
Il permet d'insérer automatiquement :
- des diapositives de sommaire
- des diapositives de progression
- des rappels de progression dans toutes les diapos (titre du chapitre en cours)
- numérotation des diapositives
Rien de bien compliqué en plus :

Bref, assez pratique pour gagner du temps sur ces taches répétitives.
Si ça vous intéresse, voici le site web : AutoSummary pour PowerPoint 2010.
Si vous aussi vous habitez en Islande (ou Canada, Suède, Norvège, USA...), vous n'avez pas envie de passer à côté d'une aurore boréale parce que vous êtes en train de faire le geek.
Les prévisions par heure peuvent être trouvées ici. C'est présenté sous forme de graphique, mais il est possible de récupérer directement les données sous format texte.
Voici un script shell tout simple, qui va vérifier les dernières prévisions pour la prochaine heure. En cas d'alerte supérieure à 3 (configurable, selon votre latitude), vous obtiendrez une alerte Growl. Ce script est donc spécialisé pour Mac, mais vous pourrez facilement remplacer l'appel à growlnotify par un envoi de mail par exemple.
#!/bin/sh
### Northern Lights alert ###
# The script will stop if a variable was not initialized
set -u
# Treeshold level
ALERT_LEVEL=3.0
# Get data
wget -q -O aurores.txt http://www.swpc.noaa.gov/wingkp/wingkp_list.txt || exit 1;
# Get next hour prevision
nextLevel=`tail -n1 aurores.txt | awk '{print $10}'`
# Comparison
if [ $(bc <<< "$ALERT_LEVEL <= $nextLevel") -eq 1 ]
then
growlnotify -p 1 -m "Northern lights alert ! Next Kp level is : $nextLevel, in 1 hour." -a iPhoto
fi
Il n'y a plus qu'à ajouter l'exécution de ce script à votre Crontab toutes les demi-heures.
Grâce à ce script, j'ai déjà réussi à en capturer quelques unes :
Quand on travaille en équipe avec SVN (Subversion), il est recommandé de préciser les modifications faites à chaque commit. Vous pouvez aussi prendre les devants, et interdire un commit sans message.
Pour cela, il faut utiliser un hook pre-commit. Utilisez donc le contenu suivant pour le fichier repositories/XXX/hooks/pre-commit :
# Message de commit obligatoire
SVNLOOK=/usr/bin/svnlook
$SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]" > /dev/null
RESULT=$?
if [ $RESULT -eq "0" ];
then
# c'est bon, on peut sortir au statut 0
exit 0
else
# c'est pas bon, on lance un message et on sort au statut 1
# ce qui va bloquer la propagation du commit
MESSAGE="Message de log obligatoire !"
echo $MESSAGE 1>&2
exit 1
fi
Vous voulez insérer une image dans Word 2008 (version pour Mac Os X), mais vous obtenez systématiquement le message :
The application cannot open this file. This file is an unsupported
graphic format or may be damaged. Try opening the graphic in another
application.
Je me suis moi aussi tiré les cheveux la dessus, en croyant à un histoire d'encodage, png/gif/jpeg, mais que nenni, il suffit de fermer la boite "Styles" de la fenêtre de formatage. Et hop, ça marche, allez comprendre.
Ce billet (en plus de permettre à d'autres personnes de perdre moins de temps quand ça leur arrivera), est surtout un coup de gueule contre Microsoft et son Word pour Mac bien plus que décevant. Et malheureusement, ce n'est pas Open Office qui va dire le contraire, quand on est dans une boite qui utilise le docx (ben oui, sous Windows ça marche très bien, et c'est très joli...). Parce que Open Office et le docx, c'est pas encore ça.
En plus, moi qui ai un clavier reconfiguré pour Dvorak, je n'ai pas de touche "z", ni en minuscule, ni en majuscule. C'est drôle non
? Obligé de faire des copier/coller...
Ôôô monde cruel !
Bonjour à tous,
Voici un comportement peu intuitif que je viens de remarquer dans MySql.
Un exemple est bien plus explicite qu'un long texte, alors voici :
create table tb (
a int,
b int,
c int,
unique index (a,b,c)
);
insert into tb(a,b,c) values (null,null,null); -- ok
insert into tb(a,b,c) values (null,null,null); -- ok
insert into tb(a,b,c) values (null,null,null); -- ok
insert into tb(a,b,c) values (1,null,null); -- ok
insert into tb(a,b,c) values (1,2,null); -- ok
insert into tb(a,b,c) values (1,2,3); -- ok
insert into tb(a,b,c) values (1,null,null); -- ok (contrairement à ce qu'on pourrait penser)
insert into tb(a,b,c) values (1,2,null); -- ok (contrairement à ce qu'on pourrait penser)
insert into tb(a,b,c) values (1,2,3); -- echec
Ceci me trouble un peu, au final une valeur NULL se comporte comme un "joker", qui annule la contrainte d'unicité.
En tout cas, c'est à savoir !
PHP, malgré la sortie de sa version 5.3 cet été, a toujours quelques lacunes. Parmi l'une d'elle, les classes Friend seraient bien utile.
Visiblement, ce n'est pas au programme, car comme il est élégamment expliqué ici, "long ago, we decided against 'friend' declarations".
Le principe de classes Friend consiste à permettre à une classe d'accéder aux attributs et fonctions privées d'une autre. Ceci est par exemple utile quand on veut implémenter une classe Data Mapper qui fait le lien entre une classe du modèle métier et le modèle de données. Pour sauvegarder un objet en base de données (ou le charger), elle a besoin de définir ses attributs, même ceux privés.
Une manière de contourner cette limitation est peu élégante mais relativement efficace : utiliser les méthodes magiques __get, __set et __call de PHP.
Ainsi, si B essaye d'accéder à un attribut privé de A, la méthode A::__get() sera appelée avec comme paramètre le nom de l'attribut demandé. Il est alors nécessaire de savoir qui demande l'accès à cet attribut : est-ce une classe "Friend" ou pas.
Pour cela, on utilise debug_backtrace() (beurk, oui), qui nous permet de connaitre la classe à l'origine de l'appel. Une petite vérification sur le nom de la classe et on renvoie la valeur de l'attribut demandé.
Voici un exemple sur __get et __set :
public function __get($attribut)
{
// Accès aux variables privées autorisé pour les Data Mapper
// Note : une variable privée commence par '_'
if ($attribut[0] == '_') {
$trace = debug_backtrace();
if (isset($trace[1]['class'])) {
$classname = $trace[1]['class'];
if (strpos($classname, 'Mapper_')) {
return $this->$attribut;
}
}
}
// Accès à un attribut non autorisé
throw new Exception('Accès à un attribut non autorisé ou inexistant : '
. get_class() . '::' . $attribut);
}
public function __set($attribut, $valeur)
{
// Accès aux variables privées autorisé pour les Data Mapper
// Note : une variable privée commence par '_'
if ($attribut[0] == '_') {
$trace = debug_backtrace();
if (isset($trace[1]['class'])) {
$classname = $trace[1]['class'];
if (strpos($classname, 'Mapper_')) {
return $this->$attribut = $valeur;
}
}
}
// Accès à un attribut non autorisé
throw new Exception('Modification d\un attribut non autorisé ou inexistant : '
. get_class() . '::' . $attribut);
}
Cet exemple autorise l'accès aux variables privées et protégées de cette classe à n'importe quelle classe contenant "Mapper_" dans son nom (i.e. Data Mapper). Par contre ce code suppose que vous avez nommé vos variables privées en respectant les conventions de nommage PEAR.
Alors, à quand les classes Friend dans PHP ? Le polymorphisme ? Et l'héritage multiple :-) ?
Rien de bien constructif dans cet article, c'est sur. Mais c'est toujours marrant de faire des statistiques sur un peu tout et n'importe quoi.
Alors comment construire un graphique qui va nous montrer l'évolution du nombre de révision d'un repository svn en fonction du temps ?
Déjà, la source des données :
svn log /home/matthieu/myrepository | grep -E "^r[0-9]+" | awk '{ print $5, $1 }' | sed 's/r//' > log.txt
Ceci va générer un fichier texte contenant les dates des différentes revisions.
Ensuite, à partir de cette source de données, pour générer un graphique, nous allons utiliser gnuplot. Sous Linux, ou Mac Os X (avec Fink installé), vous pouvez le récupérer directement :
apt-get install gnuplot
Créez le fichier qui sera utilisé pour génerer le graphique avec ce contenu (script dont je ne suis pas l'auteur bien entendu) :
set xdata time
# The format of time found in the file
set timefmt "%Y-%m-%d"
set term png
set output "log.png"
set xlabel "Date"
set ylabel "Revision"
set title "Revisions du svn"
# The time format actually shown on the x-axis
set format x "%Y"
# It's tricky to get the tics right in time mode, as you have to specify increments in seconds.
# I find it easier to just specify what dates I want shown
set xtics ("2009-1-1", "2010-1-1")
set nokey
plot "log.txt" using 1:2 with lines
Ensuite il ne reste plus qu'à lancer la génération du graphique :
gnuplot graphesvn.gnuplot
(avec "graphesvn.gnuplot" le nom du fichier qu'on a créé)
Le résultat est simple, mais suffisant non ?
(source en anglais)
PHP 5.3 est enfin sorti en version finale ! Et c'est pas trop tôt.
Le principal défaut qu'il vient corriger, à mes yeux, est le problème du Late Static Binding. Maintenant, il est possible de créer des vraies classes Singleton et d'utiliser ce design pattern grâce à l'héritage.
Voici un exemple de classe Singleton, qui ne fonctionne bien entendu que sous PHP 5.3.
<?php
/**
* Classe Singleton abstraite
*/
abstract class Singleton
{
/**
* Renvoie l'instance Singleton de la classe
*/
public static function getInstance()
{
// Un tableau statique contenant les instances de
// toutes les classes filles
static $_instances = array();
// Récupère le nom de la classe appelée (PHP 5.3, Late Static Binding)
$classname = get_called_class();
// Vérifie si l'instance a déjà été chargée
if (! isset($_instances[$classname])) {
// Si l'instance n'existe pas on la charge
$_instances[$classname] = new $classname();
}
return $_instances[$classname];
}
/**
* Le constructeur peut être redéclaré dans les classes filles
* mais sera en protected pour éviter qu'il soit possible de faire
* $o = new ClasseFille() (on sera obligé d'utiliser getInstance())
*/
protected function __construct() {}
/**
* On déclare cette méchode en final private pour interdire son
* utilisation par des classes filles
*/
final private function __clone() {}
}
Maintenant il est possible de créer des classes qui héritent de cette classe Singleton, et aucune méthode (ni attribut) n'est à redéclarer. Il sera possible d'accéder à l'instance d'une classe fille uniquement par la méthode :
$instance_fille = ClasseFille::getInstance();
Les scripts Shell pour Unix, quelle galère. C'est très puissant, mais il faut parfois s'accrocher pour trouver quelques fonctionnalités classiques.
Par exemple, un script bien construit voudrait qu'en cas d'échec d'une commande, l'exécution du script s'arrête, plutôt que de continuer avec des erreurs. Pour parvenir à cela, il suffit d'activer une option qui ordonne à bash de stopper l'exécution du script si une commande retourne une erreur.
Pour l'activer : set -e
Pour la désactiver : set +e
Il est donc recommandé d'inclure cette ligne au début du script.
Une autre façon de procéder est d'utiliser le schéma suivant :
command || { echo "Erreur"; exit 1; }
Une autre source d'erreur concerne les variables. Comment vérifier simplement si une variable utilisée n'est pas définie ou initialisée, par exemple dans le cas où vous utiliser un paramètre du script qui n'a pas été renseigné.
Cela est possible grâce à la commande : set -u
Cette commande arrêtera l'exécution du script si une variable est utilisée sans avoir été initialisée.
Ce sont des petites astuces, mais qui permettent d'obtenir des scripts bien plus fiables.
Google Maps propose une API Javascript largement utilisée aujourd'hui par de nombreux sites. Cet API permet d'intégrer des cartes facilement.
Google Maps propose également un autre service de géocoding, cette fois ci non pas en Javascript mais sous la forme d'un service web REST. Son utilisation est simplissime, et d'une puissance incroyable. Un exemple tout simple consiste à récupérer les coordonnées géographiques (latitude, longitude) correspondant à une adresse.
Voici un exemple en PHP. Il requiert une clé Google Maps pour fonctionner.
/**
* Recherche les coordonnées d'une adresse avec le service Google Maps
* @param adresse string
* @return array(id_result => array(adresse_complete, latitude, longitude))
*/
function get_coordonees_from_adresse($adresse)
{
$adresse = urlencode($adresse);
$url = 'http://maps.google.com/maps/geo?q=' . $adresse . '&output=xml&oe=utf8&gl=fr&sensor=false&key=' . GMAP_KEY;
$page = file_get_contents($url);
// Parse le résultat XML
$xml_result = new SimpleXMLElement($page);
// Vérifie que la requête a réussi
if ($xml_result->Response->Status->code != 200) return array();
// Charge les adresses
$adresses = array();
foreach ($xml_result->Response->Placemark as $place) {
list($longitude, $latitude, $altitude) = explode(',', $place->Point->coordinates);
// Ajoute au tableau
$adresses[] = array('adresse_complete' => utf8_decode($place->address),
'latitude' => $latitude,
'longitude' => $longitude);
}
return $adresses;
}
Cette fonction renvoie un tableau contenant, pour chaque résultat (il peut y'en avoir plusieurs en cas d'ambiguité) l'adresse trouvée (pratique pour différencier plusieurs résultats) et la latitude/longitude.
Je dois dire qu'il est souvent très lourd, quand on visite un site quotidiennement, de retrouver dans ses pages web des services que l'on sait que l'on utilisera pas. Pour cacher les parties d'un site qui ne me servent pas, j'utilise un plugin firefox.
Voici un exemple avec la page d'accueil de vbfrance :
(cliquez pour agrandir)
Épurée non ?
Pour comparaison, l'originale.
Ces modifications sont possibles grâce à l'extension Platypus qui vous permettra de redesigner tous les sites web. Avec une interface relativement intuitive, vous pourrez supprimer toutes les parties d'un site qui ne vous intéresse pas.
Une fois la boucherie finie, vous enregistrez le travail sous forme d'un script GreaseMonkey (également très bonne extension, à installer pour que ça fonctionne). Tout est intégré automatiquement, rien de compliqué, et quand on rafraichit la page, les modifications restent. Magnifique !
Ceci dit, j'espère que les développeurs ne m'en voudront pas de tronquer tant leur site web. Grâce à cette extension, on sent encore plus le web sous sa forme "service", et cet aspect me séduit beaucoup.
Car, par exemple les rubriques Livre, Emploi, Comparateur de prix, blog, sondages, sponsors, IT, formations vidéos, Appels d'offres, Logiciels, photothèque, news IT, news .Net et VIDÉOS DROLES (sérieux ?)
Y'a un moment ou l'aspect programmation se perd un peu dans ce fouillis, et le reste ne fait que surcharger ma page. C'est bien entendu un avis personnel lié à mon utilisation.
[Aperçu non disponible]
Chargement de l'image
Cliquez n'importe où pour annuler
Bonjour à tous,
Voici une petite présentation de XML/SWF Charts. C'est une API de génération de graphique pour vos sites web très simple, et TRÈS puissante. Gabe me l'a conseillé il y'a peu (j'avais l'habitude d'utiliser Artichow), et c'est sans comparaison.
Voyez dejà le rendu, pour vous faire une idée :
Voici ses fonctionnalités :
-
Rendu très professionnel
-
Objet Flash, indépendant des données (une fois chargé par le navigateur, il n'est plus rechargé même si les données changent)
- Génération des graphiques à partir d'un fichier XML (très pratique ! ce fichier peu contenir du PHP pour générer les données dynamiquement)
-
Indépendant du langage du site web (PHP, ASP...) car objet Flash utilisant un peu de Javascript, et les données sont en XML
- Possibilité que le graphe mette à jour ses données en temps réel toutes les X secondes, sans recharger la page (très très bien géré)
- Possibilité d'interaction avec l'utilisateur sur le graphe de manière complexe (simple à définir)
- Nombre de fonctionnalités incroyables...
- Projet Open Source, gratuit
Bref, vous avez peut être saisi mon enthousiasme, je suis plus qu'épaté par les possibilités offertes par cet outil. Je suis passé de graphiques "images" (avec Artichow), statiques, dépendants du PHP, à XML/SWF Charts. Et même si la documentation a tendance à fournir des exemples assez poussés, on s'y fait vite.
L'installation est très simple. Téléchargez l'archive zip ou gzip sur la page "download". Extrayez la et ouvrez le dossier avec votre navigateur. L'exemple fourni (sample.php) affiche des données d'exemple car le fichier sample.xml est vide, mais à vous de le remplir et le personnaliser.
La documentation est votre amie. Bonne chance.
Bonjour à tous,
Aujourd'hui, un petit article sur la manipulation de coordonnées géographiques dans vos applications, notamment ici dans un site web en PHP.
Cet article fait suite au peu de documentation que j'ai constaté en recherchant le web.
1ère méthode : Calculs précis
Le "calcul précis" présenté ici est déjà une approximation, mais c'est la solution qu'on rencontre le plus souvent dans les forums :
define('RAYON_TERRE', 6378137);
/**
* Retourne la distance précise à vol d'oiseau entre 2 coordonnées
* @param double latitude du point 1
* @param double longitude du point 1
* @param double latitude du point 2
* @param double longitude du point 2
* @return double Distance entre les points 1 et 2
*/
function get_distance_precis($lat1, $long1, $lat2, $long2)
{
$rlo1 = deg2rad($long1);
$rla1 = deg2rad($lat1);
$rlo2 = deg2rad($long2);
$rla2 = deg2rad($lat2);
$dlo = ($rlo2 - $rlo1) / 2;
$dla = ($rla2 - $rla1) / 2;
$a = (sin($dla) * sin($dla)) + cos($rla1) * cos($rla2) * (sin($dlo) * sin($dlo));
$d = 2 * atan2(sqrt($a), sqrt(1 - $a));
return (RAYON_TERRE * $d);
}
Bilan :
- Calcul compliqué et lent
- Propre à PHP, s'implémente difficilement dans une requête SQL (pour faire un SELECT en prenant en compte la distance par exemple)
2ème méthode : Approximation
On remarquera que le calcul suivant renvoie un résultat linéaire :
echo get_distance_precis(0.0, 0.0, 0.001, 0);
echo get_distance_precis(0.0, 0.0, 0.01, 0);
echo get_distance_precis(0.0, 0.0, 0.1, 0);
echo get_distance_precis(0.0, 0.0, 1., 0.);
111.31949079327
1113.1949079327
11131.949079327
111319.49079327
On peut donc utiliser le facteur proportionnel get_distance_precis(0.0, 0.0, 1., 0.) ce qui donne la fonction suivante :
define('CONVERSION_LATLONG_METRES', 111319.49079327);
/**
* Retourne la distance approximative à vol d'oiseau entre 2 coordonnées
* @param double latitude du point 1
* @param double longitude du point 1
* @param double latitude du point 2
* @param double longitude du point 2
* @return double Distance entre les points 1 et 2
*/
function get_distance_approx($lat1, $long1, $lat2, $long2)
{
$delta_lat = $lat2 - $lat1;
$delta_long = $long2 - $long1;
$dist_lat = $delta_lat * CONVERSION_LATLONG_METRES;
$dist_long = $delta_long * CONVERSION_LATLONG_METRES;
$distance = sqrt($dist_lat * $dist_lat + $dist_long * $dist_long);
return $distance;
}
Vérification des résultats :
echo get_distance_precis(0.0, 0.0, 0.001, 0);
echo get_distance_precis(0.0, 0.0, 0.01, 0);
echo get_distance_precis(0.0, 0.0, 0.1, 0);
echo get_distance_precis(0.0, 0.0, 1., 0.);
echo get_distance_approx(0.0, 0.0, 0.001, 0);
echo get_distance_approx(0.0, 0.0, 0.01, 0);
echo get_distance_approx(0.0, 0.0, 0.1, 0);
echo get_distance_approx(0.0, 0.0, 1., 0.);
111.31949079327
1113.1949079327
11131.949079327
111319.49079327
111.31949079327
1113.1949079327
11131.949079327
111319.49079327
Bilan :
- Calcul simple et rapide
- Peut s'implémenter facilement dans une requête SQL en utilisant le facteur de conversion.
Bonus : Faire l'inverse, décaler une latitude/longitude avec une distance
Au lieu de calculer la distance entre 2 points, on peut vouloir décaler une coordonnées (pour par exemple faire un carré autour d'un point).
Pour cela voici la fonction suivante :
define('CONVERSION_LATLONG_METRES', 111319.49079327);
/**
* Décale la latitude ou la longitude de la distance spécifiée
* @return angle de décalage
*/
function get_angle_decalage_geo($distance)
{
return $distance / CONVERSION_LATLONG_METRES;
}
Cette fonction renvoie le décalage à appliquer à une latitude ou une longitude pour obtenir un point situé à la distance précisée.
Vérification des résultats :
echo get_angle_decalage_geo(100);
echo get_distance_approx(0.0, 0.0, get_angle_decalage_geo(100), 0.);
0.00089831528411955
100
Autant l'autocomplétion est un très bon outil sous OpenOffice Writer (configuré à sa sauce), autant c'est une plaie incroyable dans Calc.
Pour le désactiver, il faut trouver l'astuce, d'autant plus que cette fonctionnalité s'appelle Insertion automatique dans Writer et Autosaisie dans Calc. Pour désactiver la première, il faut aller dans Outils > Autocorrection > Insertion automatique, et pour la seconde dans Outils > Contenu des cellules > Autosaisie.
Un peu de cohérence ne fera pas de mal.
Bonjour à tous,
English readers : if you want translation you can contact me.
Toujours dans la série NSLU2, je vous avait parlé récemment de l'installation de TorrentFlux. Je vous avait également parlé de l'optimisation du réglage de la SWAP sous Linux embarqué.
Et bien surprise : les 2 ne font pas forcément très bon ménage !
En effet, les téléchargements (surtout de gros fichiers) avaient tendance à couper régulièrement, me donnant la fameuse erreur "Torrent Died" (bien connue des utilisateurs de TorrentFlux si on en croit leur forum). En regardant les logs de ma machine, je me suis rendu compte que les scripts python de téléchargement (BitTornado) étaient tués par le système à cause d'une quantité de mémoire insuffisante.
Bizarre, car j'ai plus de 700 Mo de SWAP de libre et la mémoire utilisée à ce moment atteignait les 40 Mo. Je suppose (étant donné l'évolution chaotique et imprévisible de la répartition mémoire RAM / virtuelle pendant le téléchargement) que le script devait demander trop de mémoire d'un coup, et que le système n'avait pas le temps d'allouer de la SWAP pour combler la demande. Ça n'est que supposition, j'aimerai bien comprendre...
En tout cas c'est cohérent avec le fait qu'en rajustant la swappiness à 40% au lieu de 15%, tout marche maintenant. Je pense qu'avec 40% il hésite beaucoup moins à réserver de la mémoire SWAP et donc le système peut répondre aux demandes de mémoire soudaines plus facilement (il anticipe plus).
À noter que le système "s'enlise" plus facilement au bout de quelques heures sur de gros fichiers (une bonne partie des autres processus sont en SWAP et ne repassent pas en mémoire vive quand une partie se libère), mais c'est ça ou pas de torrent.
Bref, ça marche, c'est cool.
Les 10 derniers blogs postés
-
TechDays Paris 2012 : Session pleinière jour 3 par
Blog Technique de Romelard Fabrice le il y a 22 heures et 52 minutes
-
Mishra Reader : un lecteur RSS très Zune Style en Open Source ! par
Cyril Sansus le 02-09-2012, 08:28
-
[framework 4] Les Tasks et le Thread UI par
Fathi Bellahcene le 02-09-2012, 00:33
-
Workflow Foundation 3 a un pied dans la tombe par
Blog de Jérémy Jeanson le 02-08-2012, 22:15
-
TechDays Paris 2012 : Nouvelles tendances du poste de travail - Bring Your own PC par
Blog Technique de Romelard Fabrice le 02-08-2012, 19:42
-
TechDays Paris 2012 : System Center Service Manager 2012 Vue d’ensemble par
Blog Technique de Romelard Fabrice le 02-08-2012, 17:32
-
TechDays Paris 2012 : Pleinière second jour par
Blog Technique de Romelard Fabrice le 02-08-2012, 16:23
-
TechDays Paris 2012 : Retour d'expérience sur la mise en place d'un Cloud Privé par
Blog Technique de Romelard Fabrice le 02-08-2012, 16:04
-
TechDays Paris 2012 : Comment SharePoint a sauvé mes TechDays par
Blog Technique de Romelard Fabrice le 02-07-2012, 23:59
-
Perspective 3.0 pour Silverlight 5.0 par
Perspective le 02-07-2012, 22:39