protected/components/RISGeo.php
<?php
class RISGeo
{
public static $STREETS_INITIALIZED = false;
/** @var null|array|Strasse[] */
public static $STREETS = null;
public static $RIS_STREET_IGNORE_STREETS = [
"tal",
];
public static function get_RIS_STREET_CLEAN_REPLACES_1()
{
return [
"." => "",
"-" => "",
"ö" => "oe",
"ü" => "ue",
"ä" => "ae",
"ß" => "ss",
utf8_decode("ö") => "oe",
utf8_decode("ä") => "ae",
utf8_decode("ü") => "ue",
utf8_decode("ß") => "ss",
" \n" => " ",
"\n " => " ",
"\n" => " ",
" " => " ",
];
}
public static function get_RIS_STREET_CLEAN_REPLACES_2()
{
return [
"e ost" => "e#ost",
"ende weg" => "ende#weg",
"ortskern str" => "ortskern#str",
"frauenhofer" => "fraunhofer",
];
}
public static function addressToGeo(string $country, string $zip, string $city, string $street): ?array
{
return ris_intern_address2geo($country, $zip, $city, $street);
}
public static function init_streets()
{
if (static::$STREETS_INITIALIZED) return;
$streets_by_length = [];
$streets_by_norm = [];
$maxlength = 0;
/** @var array|Strasse[] $strassen */
$strassen = Strasse::model()->findAll();
foreach ($strassen as $strasse) {
$norm = static::ris_street_cleanstring($strasse->name);
$strasse->name_normalized = $norm;
$streets_by_norm[$norm] = $strasse;
$l = mb_strlen($norm);
if (!isset($streets_by_length[$l])) $streets_by_length[$l] = [];
$streets_by_length[$l][] = $norm;
if ($l > $maxlength) $maxlength = $l;
}
static::$STREETS = [];
for ($i = $maxlength; $i > 0; $i--) if (isset($streets_by_length[$i])) foreach ($streets_by_length[$i] as $n) {
if (!in_array($n, static::$RIS_STREET_IGNORE_STREETS)) static::$STREETS[] = $streets_by_norm[$n];
}
static::$STREETS_INITIALIZED = true;
}
public static function ris_street_cleanstring($name)
{
$name = str_replace("\r", "\n", $name);
$name = preg_replace("/[0-9]+[,\\. ]*[0-9][,\\. 0-9]*E+/s", "", $name); // greedy!
$name = preg_replace("/\n+ *[^a-z]+/si", "\n", $name); // greedy!
$name = strtolower($name);
$froms = $tos = [];
$RIS_STREET_CLEAN_REPLACES_1 = static::get_RIS_STREET_CLEAN_REPLACES_1();
foreach ($RIS_STREET_CLEAN_REPLACES_1 as $key => $val) {
$froms[] = $key;
$tos[] = $val;
}
$name = str_replace($froms, $tos, $name);
$name = str_replace("strasse", "str", $name);
$name = preg_replace("/([0-9]) +([0-9])/", "\\1#\\2", $name);
$name = preg_replace("/[\n\r]+([0-9])/", "#\\2", $name);
$name = preg_replace("/[0-9]+[,\\.][0-9]+/", "", $name);
$froms = $tos = [];
$RIS_STREET_CLEAN_REPLACES_2 = static::get_RIS_STREET_CLEAN_REPLACES_2();
foreach ($RIS_STREET_CLEAN_REPLACES_2 as $key => $val) {
$froms[] = $key;
$tos[] = $val;
}
$name = str_replace($froms, $tos, $name);
$name = str_replace(" ", "", $name);
return $name;
}
public static function suche_strassen($str)
{
static::init_streets();
$antragtext = static::ris_street_cleanstring($str);
$streets_found = [];
foreach (static::$STREETS as $street) {
$offset = -1;
$last_offset = -1;
while (($offset + 3 < mb_strlen($antragtext)) && ($offset = mb_strpos($antragtext, $street->name_normalized, $offset + 1)) !== false) {
if ($offset == $last_offset) {
$offset += 10;
continue;
}
$danach = mb_substr($antragtext, $offset + mb_strlen($street->name_normalized), 10);
$nr = IntVal($danach);
$ort = ($nr > 0 && $nr < 1000 ? $street->name . " $nr" : $street->name);
$falsepositive = false;
if (mb_substr($antragtext, $offset - 11, 11) == "haltestelle") $falsepositive = true;
if ($street->name_normalized == "richardstr" && mb_substr($danach, 0, 2) == "au") $falsepositive = true;
if (!$falsepositive && !in_array($ort, $streets_found)) {
$streets_found[] = RISTools::toutf8($ort);
}
for ($i = $offset; $i < $offset + mb_strlen($street->name_normalized); $i++) $antragtext[$i] = "#";
$last_offset = $offset;
}
}
$streets_found_consolidated = [];
foreach ($streets_found as $street) {
$street_short = str_replace([" str", "-str"], ["str", "str"], mb_strtolower($street));
$laengeres_gefunden = false;
foreach ($streets_found as $street_cmp) {
$street_cmp_short = str_replace([" str", "-str"], ["str", "str"], mb_strtolower($street_cmp));
if (mb_strpos($street_cmp_short, $street_short) !== false && mb_strlen($street_short) < mb_strlen($street_cmp_short)) {
$laengeres_gefunden = true;
}
}
if ($laengeres_gefunden) continue;
if (preg_match("/[0-9]/siu", $street)) $streets_found_consolidated[] = $street;
else {
$mit_hausnummer_gefunden = false;
foreach ($streets_found as $street2) if (mb_strpos($street2, $street . " ") === 0 && preg_match("/[0-9]/siu", $street2)) $mit_hausnummer_gefunden = true;
if (!$mit_hausnummer_gefunden) $streets_found_consolidated[] = $street;
}
}
return $streets_found_consolidated;
}
public static function getDistanceFormula($lon, $lat, $feldl = "laenge", $feldb = "breite")
{
$lrad = deg2rad($lon);
$brad = deg2rad($lat);
$formula = 'IFNULL(';
$formula .= "(ACOS((SIN($brad)*SIN(RADIANS($feldb))) + ";
$formula .= "(COS($brad)*COS(RADIANS($feldb))*COS(RADIANS($feldl)-$lrad))) * 6371)";
$formula .= ',0)';
return $formula;
}
/**
* @param float $lat1
* @param float $lon1
* @param float $lat2
* @param float $lon2
* @return float
*/
public static function getDistance($lat1, $lon1, $lat2, $lon2)
{
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$km = $dist * 60 * 1.1515 * 1.609344;
return $km;
}
}