Group: Drupal - Innovation und Business

Forums > Forum "Module" > Article thread "Umkreissuche + Event"

Article thread - Articles 1-10 out of 10

  • Umkreissuche + Event 13 Sep 2009, 07:10 am

    Hallo Drupal Community,

    wie bekommt man mit Drupal eine Umkreissuche hin?
    Aus verschiedenen Gründen möchte ich das Gmap Modul von Google vermeiden.
    Die Umkreissuche soll auf das Event Modul angewendet werden und das Ergebniss
    in einer Liste angezeigt werden.
  • Re: Umkreissuche + Event 13 Sep 2009, 5:56 pm

    Wie wäre es, per »Views« eine Event-Tabelle nach PLZ durchsuch- und sortierbar machen. Abgesehen von der Einteilung nach PLZ wüsste ich nicht, wie man die Event-Locations sonst filtern könnte.

    Vielleicht hilft auch das Modul »Finder-Wizard«? Damit kann man Suchanfragen immer weiter eingrenzen.

    Viele Grüße
    – Johannes Hartmann –
    This article was modified on 13 Sep 2009 at 09:11 pm.
  • Re^2: Umkreissuche + Event 14 Sep 2009, 08:29 am

    Es gibt GEO-Datenbanken, die zu den Orten die GEO-Koordinaten haben. Über diese Daten lässt sich dann die Entfernung zwischen zwei Punkten berechnen.

    Insgesamt wird dafür das Modul Location benötigt. Ich weiß nicht, wie weit dies nun ist. Vor einem Jahr war es noch 'sehr individuell' und für eine vernünftige Umkreissuche musste noch einiges angepasst, bzw. dazu geschrieben werden.
  • Article only visible to registered members
  • Re^4: Umkreissuche + Event 14 Sep 2009, 12:58 pm

    Ich denke eine echte Umkreissuche mit 10/20/50/100 km bekomme ich allene mit Views nicht hin.
    Wie bekomme ich eine verbindung zwischen den Modulen Event + Location + Search ?
  • Re^5: Umkreissuche + Event 14 Sep 2009, 2:44 pm

    Markus, ich habe das lieber selbst geschrieben und kann Dir den Code dafür auch gerne zur Verfügung stellen.

    Dafür verwende ich OpenGeoDB-Daten als Grundlage und habe ein Views-Handler fürs Filtern/Sortieren geschrieben.

    -- Dirk
  • Re^6: Umkreissuche + Event 14 Sep 2009, 3:34 pm

    Markus, ich habe das lieber selbst geschrieben und kann Dir den Code dafür auch gerne zur Verfügung stellen.
     
    Dafür verwende ich OpenGeoDB-Daten als Grundlage und habe ein Views-Handler fürs Filtern/Sortieren geschrieben.

    Den Ansatz meinte ich. :)
  • Re^7: Umkreissuche + Event 16 Sep 2009, 9:26 pm

    Mit einem fertigen Modul kann ich leider nicht dienen, aber mit einem Auszug. Hier ein Code-Snippet, der eine fertige Umkreissuche (OPenGeoDB) für Drupal bereitstellt.

    Mit ein wenig Arbeit läßt sich hieraus ein komplettes Modul machen. Die eigentlichen Suchroutinen (class Umkreissuche) habe ich selber aus dem Internet. Weiß nicht mehr woher. Im Zweifel Google befragen.

    Benötigt wird natürlich noch die OpenGeoDB, die händisch in die DB geladen werden muss.
    http://opengeodb.hoppe-media.com/

    <code>
    <?php

    class Umkreissuche {
    // Erdradius in Kilometern
    private $Erdradius = 6371;
    // mysql link identifier
    private $db;
    // Datentabelle
    private $table = false;
    // Fehler zeigen?
    public $zeigeFehler = true;

    public function __construct($db, $table = 'user_location') {
    if (!is_resource($db) || get_resource_type($db) != 'mysql link') {
    trigger_error('Keine MySQL-Ressource übergeben', E_USER_ERROR);
    }
    $this->db = $db;
    $this->table = $table;

    // leere Koordinaten in Tabelle füllen
    $sql = 'SELECT ID, PLZ
    FROM {user_location}
    WHERE
    KoordX = 0
    AND KoordY = 0
    AND KoordZ = 0
    ';
    $re = db_query($sql);
    while ($rd = db_fetch_object($re)) {
    if (!$this->Plz2Koord($rd->PLZ, $lon, $lat)) {
    if ($this->zeigeFehler) {
    trigger_error('Postleitzahl ' . $rd->PLZ . ' konnte nicht zugeordnet werden', E_USER_NOTICE);
    }
    continue;
    }
    $this->Kugel2Kartesisch($lon, $lat, $x, $y, $z);
    $sql = 'UPDATE {user_location}
    SET
    Longitude = %f,
    Latitude = %f,
    KoordX = %f,
    KoordY = %f,
    KoordZ = %f
    WHERE
    ID = '. (int)$rd->ID .'
    LIMIT 1
    ';
    db_query($sql, $lon, $lat, $x, $y, $z);
    }
    }

    public function Kugel2Kartesisch($lon, $lat, &$x, &$y, &$z) {
    $lambda = $lon * pi() / 180;
    $phi = $lat * pi() / 180;
    $x = $this->Erdradius * cos($phi) * cos($lambda);
    $y = $this->Erdradius * cos($phi) * sin($lambda);
    $z = $this->Erdradius * sin($phi);
    return true;
    }

    public function Plz2Koord($PLZ, &$lon, &$lat) {
    $sql = 'SELECT
    coo.lon,
    coo.lat
    FROM geodb_coordinates AS coo
    INNER JOIN geodb_textdata AS textdata
    ON textdata.loc_id = coo.loc_id
    WHERE
    textdata.text_val = "' . mysql_real_escape_string($PLZ, $this->db) . '"
    AND textdata.text_type = "500300000"
    LIMIT 1';
    $re = mysql_query($sql, $this->db);
    if (mysql_num_rows($re) != 1) {
    return false;
    }
    list($lon, $lat) = mysql_fetch_row($re);
    return true;
    }

    public function Suche($PLZ, $Radius, $Spalten = array(), $Reihenfolge = false, $Richtung = 'ASC') {
    if (!is_array($Spalten) || count($Spalten) == 0) {
    $Spalten = '*';
    } else {
    $Spalten = '`' . implode('`, `', $Spalten) . '`';
    }

    if (!$this->Plz2Koord($PLZ, $lon, $lat)) {
    if ($this->zeigeFehler) {
    trigger_error('Postleitzahl ' . $PLZ . ' konnte nicht zugeordnet werden', E_USER_NOTICE);
    }
    return false;
    }
    $this->Kugel2Kartesisch($lon, $lat, $UrsprungX, $UrsprungY, $UrsprungZ);

    $sql = 'SELECT ' . $Spalten . '
    FROM {user_location}
    WHERE
    KoordX >= ' . ($UrsprungX - $Radius) . '
    AND KoordX <= ' . ($UrsprungX + $Radius) . '
    AND KoordY >= ' . ($UrsprungY - $Radius) . '
    AND KoordY <= ' . ($UrsprungY + $Radius) . '
    AND KoordZ >= ' . ($UrsprungZ - $Radius) . '
    AND KoordZ <= ' . ($UrsprungZ + $Radius) . '
    AND POWER(' . $UrsprungX .' - KoordX, 2)
    + POWER(' . $UrsprungY .' - KoordY, 2)
    + POWER(' . $UrsprungZ .' - KoordZ, 2)
    <= "' . pow(2 * $this->Erdradius * sin($Radius / (2 * $this->Erdradius)), 2) . '"';
    if ($Reihenfolge && strpos($Spalten, $Reihenfolge) !== false) {
    $Richtung = (strtoupper($Richtung) == 'DESC') ? 'DESC' : 'ASC';
    $sql .= "\n" . 'ORDER BY `' . $Reihenfolge . '` ' . $Richtung;
    }
    $re = db_query($sql);
    $result = array();
    while ($rd = db_fetch_object($re)) {
    $result[] = $rd;
    }
    return $result;
    }

    }



    #Für den User ein Profilfeld "PLZ" anlegen und diese bei der Verwendung an diese Funktion übergeben.
    function mymodule_fetchDistanceByPLZ($plz_1, $plz_2)
    {
    $database = 'geodb';
    #Unterstützung von 4- und 5-stelligen PLZ (z.B. Schweiz)
    if((strlen($plz_1) == 5 || strlen($plz_1) == 4) && (strlen($plz_2) == 5 || strlen($plz_2) == 4)){

    // Statement to query the Distance from the OpenGeoDB database
    // 1.85201 is the conversion factor from nautical miles to kilometers
    $sql = "
    SELECT
    DEGREES(
    ACOS(
    SIN(RADIANS(c1.lat)) * SIN(RADIANS(c2.lat))
    + COS(RADIANS(c1.lat)) * COS(RADIANS(c2.lat))
    * COS(RADIANS(c1.lon - c2.lon))
    ) * 60 * 1.85201
    ) AS distance
    FROM
    geodb_textdata t1,
    geodb_textdata t2,
    geodb_coordinates c1,
    geodb_coordinates c2
    WHERE
    t1.text_type = 500300000
    AND t2.text_type = 500300000
    AND t1.text_val = \"{$plz_1}\"
    AND t2.text_val = \"{$plz_2}\"
    AND c1.loc_id = t1.loc_id
    AND c2.loc_id = t2.loc_id
    ";

    $query = mysql_query($sql);

    if($row = mysql_fetch_assoc($query))
    {
    // get the database result and round it
    if($row['distance'] < 100)
    // return distance (in km) round to one position after decimal point
    return round($row['distance'], 1);
    else
    // round to no position after decimal point from 100km and more
    return round($row['distance'], 0);
    }
    else
    {
    // No result found
    return -1;
    }
    }elseif($plz_1 == $plz_2){
    return 0; // Same country codes - distance is null
    }else{
    return -1; // At least one of both codes is invalid
    }

    }

    /*
    * Beim Aktualisieren des Profils wird die Funktion aufgerufen, um die PLZ zu syncronisieren. In einem eigenen Modul sollte diese Funktion in hook_user($op = 'update') aufgerufen werden.
    */
    function mymodule_update_user_location($uid){

    $zip = _get_users_zip($uid); #Liest PLZ aus Userprofil aus.
    $sql = 'SELECT
    coo.lon,
    coo.lat
    FROM geodb_coordinates AS coo
    INNER JOIN geodb_textdata AS textdata
    ON textdata.loc_id = coo.loc_id
    WHERE
    textdata.text_val = "'.$zip.'"
    AND textdata.text_type = "500300000"
    LIMIT 1';
    $re = db_query($sql);
    if (mysql_num_rows($re) != 1) {
    return false;
    }
    while($data = db_fetch_object($re)){
    $lon = $data->lon;
    $lat = $data->lat;
    }
    $is_set = db_result(db_query("SELECT ID FROM {user_location} WHERE uid = %d",$uid));
    $sql = "INSERT INTO {user_location} (uid, PLZ, Longitude, Latitude) VALUES (%d, %d, %f, %f)";
    if(!$is_set){
    $res = db_query($sql, $uid, $zip, $lon, $lat);
    }else{
    #TODO: Update query
    }
    }
    ?>

    </code>

    Gruß
    Alex
  • Re^6: Umkreissuche + Event 04 Nov 2009, 3:26 pm

    @Dirk Gomez: Hast Du das Modul veröffentlicht? Ich würde es mir gern ansehen.
    This article was modified on 04 Nov 2009 at 03:27 pm.
  • Re^6: Umkreissuche + Event 11 Nov 2009, 09:51 am

    Dirk Gomez schrieb:
    Markus, ich habe das lieber selbst geschrieben und kann Dir den Code dafür auch gerne zur Verfügung stellen.
     
    Dafür verwende ich OpenGeoDB-Daten als Grundlage und habe ein Views-Handler fürs Filtern/Sortieren geschrieben.
     
    -- Dirk

    Hallo Dirk,

    genau das suche ich auch seit geraumer Zeit. Wäre es möglich, dass du mir den Code auch zur verfügung stellst? Das wäre klasse.

    Gruss, Stefan.

Forums > Forum "Module" > Article thread "Umkreissuche + Event"

Top