Benutzer:Erik/Extension:Häfen in der Nähe: Unterschied zwischen den Versionen

ToDo: Testumgebungen spezifiziert.
Argonaut (Diskussion | Beiträge)
ToDo: php4/5/7
 
(6 dazwischenliegende Versionen von einem anderen Benutzer werden nicht angezeigt)
Zeile 24: Zeile 24:
;lat:Angabe der geografischen Breit des Ausgsngspunkts
;lat:Angabe der geografischen Breit des Ausgsngspunkts
;dist:Der maximal Abstand vom Ausgangspunkt, den ein Hafen haben darf
;dist:Der maximal Abstand vom Ausgangspunkt, den ein Hafen haben darf
;showdist:Mit showdist="yes" wird die Anzeige der Distanzen aktiviert
;max:Die maximale Anzahl von angezeigten Häfen
;max:Die maximale Anzahl von angezeigten Häfen


Zeile 33: Zeile 34:


Eine lauffähige Installation des Scripts gibt es [http://www.erik-hansen.de/wiki/index.php?title=H%C3%A4fen_in_der_N%C3%A4he hier]. Dort kann auch mit den Einstellungen experimentiert werden.
Eine lauffähige Installation des Scripts gibt es [http://www.erik-hansen.de/wiki/index.php?title=H%C3%A4fen_in_der_N%C3%A4he hier]. Dort kann auch mit den Einstellungen experimentiert werden.
== Versionen ==
;2007-03-04:Die Distanzanzeige ist nun per default deaktiviert. Sie kann über das Attribut showdist aktiviert werden.
;2007-03-03:Fix für PHP4. Die benutzen DOM-Funktionen von PHP5 waren nicht rückwärtskompatibel. Die Umstellung auf DOM XML war zu aufwendig. Daher die 'saubere' Lösung: Erstellen eines Parsers.
;2007-03-02:Initiale Version


== Installation ==
== Installation ==
Zeile 38: Zeile 45:
Das folgende Script (NearbyPlacesExtension.php) muss im Extensions-Verzeichnis abgelegt und die Zeile <code>require_once("./extensions/NearbyPlacesExtension.php");</code> muss zu der LocalSettings.php hinzugefügt werden.
Das folgende Script (NearbyPlacesExtension.php) muss im Extensions-Verzeichnis abgelegt und die Zeile <code>require_once("./extensions/NearbyPlacesExtension.php");</code> muss zu der LocalSettings.php hinzugefügt werden.


  <?php  
  <?php
// HISTORY
// 2007-03-04 : The display of the distance is no deactivated by default.
//              It can be activated using the showdist attribute.
// 2007-03-04 : Fix for PHP 4
//              Instead of DOM or DOM XML, the xml parser functions are used
// 2007-03-02 : Initial implemtation
// TODO
// - debug output
// - testing
// - lat and lon in degrees and minutes
// - improved retrival of places
// - error handling
// - config file
// - documentation
// - output data to be selected by attributes
// - error handling
   
   
  // register the extension
  // register the extension
Zeile 48: Zeile 73:
         'name' => 'Nearby Places',
         'name' => 'Nearby Places',
         'author' => 'Erik Hansen',
         'author' => 'Erik Hansen',
         'url' => 'http://www.skipperguide.de/wiki/Benutzer:Erik',
         'url' => 'http://www.skipperguide.de/wiki/Benutzer:Erik/Extension:H%C3%A4fen_in_der_N%C3%A4he',
         'description' => 'Shows a list of places near a given place',  
         'description' => 'Shows a list of places near a given place',
   
   
  );
  );
Zeile 55: Zeile 80:
  // initialize this extension
  // initialize this extension
  // register nearbyplaces as parser hook.
  // register nearbyplaces as parser hook.
  function wfNearbyPlacesExtension() {  
  function wfNearbyPlacesExtension() {
   
   
         global $wgParser;
         global $wgParser;
         $wgParser->setHook( "nearbyplaces", "npeShowNearbyPlaces" );  
         $wgParser->setHook( "nearbyplaces", "npeShowNearbyPlaces" );
   
   
  }
  }
Zeile 72: Zeile 97:
   
   
  }
  }
// XML Parser Class
class npeCParser {
var $places;
var $tag;
var $description;
var $placename;
var $coordinates;
var $parser;
// constructor
function npeCParser() {
$this->places = array();
$this->tag = "";
$this->description = "";
$this->placename = "";
$this->coordinates = "";
}
// initialize variables for every new placemark
// store the current tag for use within die characterData function
function startElement($parser, $name, $attrs) {
if ($name == "PLACEMARK") {
$this->description = "";
$this->placename = "";
$this->coordinates = "";
}
$this->tag = $name;
}
// store the data from the closed placemark
function endElement($parser, $name) {
if ($name == "PLACEMARK") {
$this->places[] = array ("name"        => trim($this->placename),
                        "description" => trim($this->description),
                        "coordinates" => trim($this->coordinates));
}
}
// store the data of the tags
function characterData($parser, $data) {
switch ($this->tag) {
case "NAME":
$this->placename .= $data;
break;
case "DESCRIPTION":
$this->description .= $data;
break;
case "COORDINATES":
$this->coordinates .= $data;
break;
}
}
// parse the xml data
function parse($xml) {
$this->parser = xml_parser_create();
xml_set_object($this->parser, $this);
xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
xml_set_element_handler($this->parser, "startElement", "endElement");
xml_set_character_data_handler($this->parser, "characterData");
xml_parse($this->parser, $xml);
xml_parser_free($this->parser);
return $this->places;
}
}
   
   
  // this function  
  // this function  
Zeile 103: Zeile 205:
  $max_cnt = 10;
  $max_cnt = 10;
  }
  }
        $show_distance = false;
        if (isset($argv["showdist"])) {
                if ($argv["showdist"] == "yes") {
                        $show_distance = true;
                }
        }
   
   
  // initialize the array for the found places
  // initialize the array for the found places
Zeile 109: Zeile 218:
  // create a new dom instance and load the kml file into it
  // create a new dom instance and load the kml file into it
  $xml = file_get_contents("http://www.skipperguide.de/extension/GoogleEarthExport.php");
  $xml = file_get_contents("http://www.skipperguide.de/extension/GoogleEarthExport.php");
  $dom = new DomDocument;
  $dom->loadXML($xml);
// create a new Parser and parse the retrieved kml file
  $parser = new npeCParser();
  $places = $parser->parse($xml);
   
   
  // pick all placemarks from the kml-File
  // pick all placemarks from the kml-File
  // In case none is found we are done already.
  // In case none is found we are done already.
  $places = $dom->getElementsByTagName('Placemark');
  if (count($places) == 0)
if ($places->length == 0)
  return ("Es wurden leider keine Häfen gefunden (0).");
  return ("Es wurden leider keine Häfen gefunden.");
   
   
  // parse through all palces from the kml file
  // parse through all palces from the kml file
  foreach ($places as $place) {
  foreach ($places as $place) {
   
   
list($lon, $lat) = sscanf($place["coordinates"], "%f,%f");
  // in case the difference in nm between the latitudes is  
  // in case the difference in nm between the latitudes is  
          // lager than the distance, we do not hat to proceed any
          // lager than the distance, we do not hat to proceed any
          // further with this place
          // further with this place
$lat = $place->getElementsByTagName('latitude')->item(0)->nodeValue;
  if (abs($lat - $req_lat) >> ($max_dist / 3600.0)) {
  if (abs($lat - $req_lat) >> ($max_dist / 3600.0)) {
  continue;
  continue;
Zeile 136: Zeile 246:
  // In case the distance is larger than max_dist,
  // In case the distance is larger than max_dist,
  // this place will be discarded.
  // this place will be discarded.
$lon = $place->getElementsByTagName('longitude')->item(0)->nodeValue;
  $b = $lat - $req_lat;
  $b = $lat - $req_lat;
  $l = $lon - $req_lon;
  $l = $lon - $req_lon;
Zeile 149: Zeile 259:
  // in case we have come that far, the place will be added
  // in case we have come that far, the place will be added
  // to the list of places within the requested range
  // to the list of places within the requested range
$description = $place->getElementsByTagName('description')->item(0)->nodeValue;
  list($link) = sscanf($place["description"], "http://www.skipperguide.de/wiki/%s");
$name = $place->getElementsByTagName('name')->item(0)->nodeValue;
$nearby_places[] = array ("lat" => $lat,
  list($link) = sscanf($description, "http://www.skipperguide.de/wiki/%s");
                          "lon" => $lon,
  $nearby_places[] = array ("lat" => $lat, "lon" => $lon, "dist" => $dist, "name" => $name, "link" => $link);  
                          "dist" => $dist,
                          "name" => $place["name"],
                          "link" => $link);
   
   
  }
  }
Zeile 158: Zeile 271:
  // check wether any places have been found.
  // check wether any places have been found.
  if (count($nearby_places) == 0)
  if (count($nearby_places) == 0)
  return ("Es wurden leider keine Häfen gefunden.");  
  return ("Es wurden leider keine Häfen gefunden (1).");
   
   
  // sort all places using npeCmpPlacesByDist for comparation
  // sort all places using npeCmpPlacesByDist for comparation
Zeile 171: Zeile 284:
  $cnt = 0;
  $cnt = 0;
  foreach ($nearby_places as $place) {
  foreach ($nearby_places as $place) {
 
$output .= "[[" . $place["link"] . "|" . $place["name"] . "]] (" . number_format($place["dist"], 0) . "sm)&nbsp;&#124;\n";
                $output .= "[[" . $place["link"] . "|" . $place["name"] . "]]";
                if ($show_distance == true) {
                        $output .= " (" . number_format($place["dist"], 0) . "sm)";
                }
                $output .= "&nbsp;&#124;\n";
   
   
  $cnt++;
  $cnt++;
Zeile 197: Zeile 314:
;Test mit verschiedenen Wiki-Versionen
;Test mit verschiedenen Wiki-Versionen
:Bisher wurde die Extension nur mit 1.6.0, 1.7.1, 1.9.3 getestet. Andere Versionen müssen noch getestet werden. Auch wurde bei den Tests nur PHP 5 verwendet. Läuft das Script auch mit PHP 4?
:Bisher wurde die Extension nur mit 1.6.0, 1.7.1, 1.9.3 getestet. Andere Versionen müssen noch getestet werden. Auch wurde bei den Tests nur PHP 5 verwendet. Läuft das Script auch mit PHP 4?
::m.E. uninteressant. php7 ist eher die Frage.--[[Benutzer:Argonaut|Argonaut]] ([[Benutzer Diskussion:Argonaut|Diskussion]]) 17:00, 8. Nov. 2017 (UTC)
:Bisherige Testumgebungen:
:Bisherige Testumgebungen:
:* MediaWiki: 1.6.0, PHP: 5.1.2 (apache2handler), MySQL: 5.0.18  
:* MediaWiki: 1.6.0, PHP: 5.1.2 (apache2handler), MySQL: 5.0.18  
Zeile 209: Zeile 327:
;Dokumentation
;Dokumentation
:Wie immer könnte die besser sein ;)
:Wie immer könnte die besser sein ;)
;Fehlerbehandlungen
:Müssen noch hinzu gefügt werden. Sind bisher noch nicht vorhanden.
== Mathematisches ==
===Verfahren===
Breitenunterschied (b) in nm sind zunächst recht einfach zu berechnen. Er ergibt sich aus der Differenz (Δφ) von der Breiten von Ausgangspunkt zu Endpunkt. Der Längenunterschied (a) ist nicht mehr ganz so einfach zu berechnen, da eine Bogenminute nur am Äquator einer sm entpricht. Hier muss der Abweitung (Δλ) zwischen den beiden Punkten je nach Breite skaliert werden. Als Skalierungsfaktor ergibt sich der Cosinus der Breite. Da die beiden Punkte auf verschiedenen Breiten liegen können wird die mittlere Breite (Mittelbreite φ<sub>M</sub>) dafür genommen. Somit ergibt sich aus der Abweitung (Δλ) der Längenunterschied (a). Längen- (a) und Breitenunterschied (b) bilden Gegenkathete (a) und Ankathete (b) eines rechtwinkligen Dreiecks. Der zu steuernde Kurs (α) ist der arctan von Längenunterschied (a) geteilt durch den Breitenunterschied (b). Die Distanz (Länge der Hypothenuse) ergibt sich dann aus dem Breitenunterschied (b) geteilt durch den cosinus der mittleren Breite (φ<sub>M</sub>) skaliert mit 60, um von Grad auf sm umzurechnen.
Dieses Verfahren funktioniert nur bei kleineren Distanzen, bzw. Breitenunterschieden.
=== Formeln ===
;Breitenunterschied:b = Δφ = φ<sub>B</sub> - φ<sub>A</sub>
;Abweitung:Δλ = λ<sub>B</sub> - λ<sub>A</sub>
;Mittelbreite:φ<sub>M</sub> = ½ (φ<sub>A</sub> + φ<sub>B</sub>)
;Längenunterschied:a = Δλ * cos(φ<sub>M</sub>)
;Winkel:α = arctan(a/b) = arctan((Δλ/Δφ) * cos(φ<sub>M</sub>))
;Distanz:d = 60 * b / cos(α)
===Zum Nachlesen===
* Gunter Herdam: '''Astronomische Navigation''', 3. Auflage September 2001, Eingenverlag, S. 101ff [http://www.hmi.de/bsg/astro/index.html]
* Werner Kumm, Hans-Dieter Lübbers, Harald Schultz: '''Sporthochseeschifferschein''', 2. Auflage 1999, Delius Klasing, S. 16ff [http://www.delius-klasing.de/shop/detail.php4?artid=1820&thema=7&rubrik=7]
* Karl-Richard Albrand, Hermann Junge: '''Formelsammlung Navigation''', DSV Verlag, S. 14 [http://www.amazon.de/Formelsammlung-Navigation-Karl-Richard-Albrand/dp/388412269X/ref=cm_taf_title_featured?ie=UTF8&tag=tellafriend-20]
* Karl-Richard Albrand, Walter Stein: '''Nautische Tafeln und Formeln''', DSV Verlag, S. 73 [http://www.amazon.de/Nautische-Tafeln-Formeln-Karl-Richard-Albrand/dp/3884121480/ref=cm_taf_title_featured?ie=UTF8&tag=tellafriend-20]