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.
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

-
Markus Westenhuber Premium Member
The company name is only visible to registered members.
-
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.
-
Johannes Hartmann Premium Member Group moderator
The company name is only visible to registered members.
-
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.

-
Frank Holldorff Premium Member Group moderator
The company name is only visible to registered members.
-
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 ?

-
Markus Westenhuber Premium Member
The company name is only visible to registered members.
-
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

-
Dirk Gomez
The company name is only visible to registered members.
-
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. :)

-
Frank Holldorff Premium Member Group moderator
The company name is only visible to registered members.
-
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

-
Alexander Brauwers Premium Member Group moderator
The company name is only visible to registered members.
-
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.
-
Lars Schröter
The company name is only visible to registered members.
-
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.

-
Stefan Pfänder
The company name is only visible to registered members.
This is a Premium feature
Send messages to other XING members - quickly and securely (SSL encryption) without needing to know the recipient's email address.
Other Premium benefits (More info)
- Would you like to have access to Advanced Search options?
- See who has been on your profile
- Profit from partner offers
