#!/usr/bin/perl -w
# -*- perl -*-
#
# $Id: mapserver_address.cgi,v 1.24 2005/10/13 07:13:27 eserte Exp $
# Author: Slaven Rezic
#
# Copyright (C) 2003 Slaven Rezic. All rights reserved.
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# Mail: slaven@rezic.de
# WWW: http://www.rezic.de/eserte/
#
use strict;
BEGIN { delete $INC{"FindBin.pm"} }
use FindBin;
use vars qw($BBBIKE_ROOT $BBBIKE_URL);
BEGIN { # XXX do not hardcode
$ENV{SERVER_NAME} ||= "";
if ($ENV{SERVER_NAME} eq 'radzeit.herceg.de') {
$BBBIKE_ROOT = "/home/e/eserte/src/bbbike/projects/www.radzeit.de/BBBike";
$BBBIKE_URL = "/BBBike";
@Strassen::datadirs = "$BBBIKE_ROOT/data";
} elsif ($ENV{SERVER_NAME} eq 'vran.herceg.de') {
$BBBIKE_URL = "/~eserte/bbbike";
} elsif ($ENV{SERVER_NAME} =~ /radzeit/i) {
if (-d "/var/www/domains/radzeit.de/www/BBBike") {
$BBBIKE_ROOT = "/var/www/domains/radzeit.de/www/BBBike";
} else {
$BBBIKE_ROOT = "/usr/local/apache/radzeit/BBBike";
}
$BBBIKE_URL = "/BBBike";
#$BBBIKE_ROOT = "/usr/local/apache/radzeit/BBBike2";
} else {
$BBBIKE_ROOT = "$FindBin::RealBin/..";
$BBBIKE_URL = "/bbbike";
}
}
use CGI qw(:standard *table);
use lib (defined $BBBIKE_ROOT ? ("$BBBIKE_ROOT",
"$BBBIKE_ROOT/lib",
"$BBBIKE_ROOT/data",
"$BBBIKE_ROOT/miscsrc",
) : (),
"/home/e/eserte/src/bbbike",
"/home/e/eserte/src/bbbike/lib",
"/home/e/eserte/src/bbbike/data",
"/home/e/eserte/src/bbbike/miscsrc",
); # XXX do not hardcode
if (!param("usemap")) {
param("usemap", "mapserver");
}
if (defined param("mapserver")) {
redirect_to_map();
} elsif (defined param("street") && param("street") !~ /^\s*$/) {
resolve_street();
} elsif (defined param("coords") && param("coords") !~ /^\s*$/) {
redirect_to_map(param("coords"));
} elsif (defined param("city") && param("city") !~ /^\s*$/) {
resolve_city();
} elsif (defined param("searchterm") && param("searchterm") !~ /^\s*$/) {
resolve_fulltext();
} elsif (defined param("latD") && param("latD") !~ /^\s*$/ &&
defined param("latM") && param("latM") !~ /^\s*$/ &&
defined param("longD") && param("longD") !~ /^\s*$/ &&
defined param("longM") && param("longM") !~ /^\s*$/
) {
my $lat = param("latD") + param("latM")/60 + param("latS")/3600;
my $long = param("longD") + param("longM")/60 + param("longS")/3600;
resolve_latlong($lat, $long);
} elsif (defined param("lat") && defined param("long") &&
param("lat") !~ /^\s*$/ && param("long") !~ /^\s*$/) {
resolve_latlong(param("lat"), param("long"));
} else {
print header,
start_html("Auswahl nach Straßen und Orten"),
h1("Auswahl nach Straßen und Orten");
show_form();
print end_html;
}
sub _form {
print start_form(-action => url(-relative=>1));
print hidden("layer", param("layer")) if param("layer");
print hidden("mapext", param("mapext")) if param("mapext");
print hidden("usemap", param("usemap"));
}
sub show_form {
print h2("Berlin");
_form;
print table({-border=>0},
Tr(
[
td(['Straße' , textfield('street'), submit(-value => "Zeigen")]),
td(['Bezirk' , textfield('citypart'), "(optional)"]),
]
)
);
print end_form, hr;
print h2("Brandenburg");
_form;
print table({-border=>0},
Tr(
[
td(['Ort' , textfield('city'), submit(-value => "Zeigen")]),
]
)
);
print end_form, hr;
print h2("Volltextsuche");
_form;
print table({-border=>0},
Tr(
[
td(['Begriff' , textfield('searchterm'), submit(-value => "Zeigen")]),
]
)
);
print end_form, hr;
print h2("Breite/Länge");
_form;
print table({-border=>0},
Tr(
[
td(['(Angaben als DDD)']),
td(['Breite' , textfield('lat')]),
td(['Länge' , textfield('long'), submit(-value => "Zeigen")]),
]
)
);
# Check -size and -maxlength, N and E if porting to other world regions.
print table({-border=>0},
Tr(
[
td(['(Angaben als DMS)']),
td(['Breite' ,
'N', textfield(-name => 'latD', -size => 2, -maxlength => 2), '°',
textfield(-name => 'latM', -size => 2, -maxlength => 2),"'",
textfield(-name => 'latS', -size => 4, -maxlength => 2), "''"]),
td(['Länge' ,
'E', textfield(-name => 'longD', -size => 2, -maxlength => 2), '°',
textfield(-name => 'longM', -size => 2, -maxlength => 2),"'",
textfield(-name => 'longS', -size => 4, -maxlength => 2), "''",
submit(-value => "Zeigen")]),
]
)
);
print end_form, hr;
if (param("usemap") ne "googlemaps") {
print start_form, submit("mapserver", "Zurück zum Mapserver"), end_form;
}
}
sub resolve_street {
require BBBikeRouting;
my $br = BBBikeRouting->new;
$br->init_context;
## XXX not enabled by default, because there is no db
## on radzeit for example
#$br->Context->UseTelbuchDBApprox(1); # XXX experimental!!!
my $start = $br->Start;
$start->Street(param("street"));
$start->Citypart(param("citypart") || undef);
my $coord = $br->get_start_position(fixposition => 0);
if (!defined $coord) {
if (!$br->StartChoices && !@{$br->StartChoices}) {
print header, start_html("Auswahl nach Straßen und Orten"), h1("Auswahl nach Straßen und Orten");
print "Nichs gefunden!
";
show_form();
print end_html;
return;
}
splice @{$br->StartChoices}, 20 if @{$br->StartChoices} > 20;
print header, start_html("Auswahl nach Straßen und Orten"), h1("Auswahl nach Straßen und Orten");
#print start_form;
_form;
print h2("Mehrere Straßen gefunden");
print radio_group
(-name=>"coords",
-values => [map { $_->Coord } @{$br->StartChoices}],
-labels => {map { ($_->Coord =>
$_->Street . " (" . $_->Citypart . (defined $_->ZIP ? ", " . $_->ZIP : "") . ")" ) } @{$br->StartChoices}},
-linebreak => "true",
), br;
print submit(-value => "Zeigen");
print end_form, hr;
show_form();
print end_html;
return;
}
my $xy = $start->Coord;
redirect_to_map($xy);
}
sub resolve_city {
my $norm = sub {
my $s = shift;
$s =~ s/([ÄÖÜ])/{"Ä"=>"ä","Ö"=>"ö","Ü"=>"ü"}->{$1}/ge;
lc $s;
};
my $city = $norm->(param("city"));
require Strassen::Core;
require Strassen::MultiStrassen;
my $s = MultiStrassen->new("orte", "orte2");
my @res;
for my $stage (0 .. 1) {
$s->init;
while(1) {
my $ret = $s->next;
last if !@{ $ret->[Strassen::COORDS()] };
my $norm_name = $norm->($ret->[Strassen::NAME()]);
if ($stage == 0 && ($norm_name eq $city ||
$norm_name =~ /^\Q$city\E\|/)) {
push @res, $ret;
} elsif ($stage == 1 && $norm_name =~ /^\Q$city/) {
push @res, $ret;
} else {
# XXX String::Approx
}
}
if (@res) {
last;
}
}
if (!@res) {
print header, start_html("Auswahl nach Straßen und Orten"), h1("Auswahl nach Straßen und Orten");
print "Nichs gefunden!
";
show_form();
print end_html;
} elsif (@res == 1) {
my $xy = $res[0]->[Strassen::COORDS()]->[0];
redirect_to_map($xy);
} else {
splice @res, 20 if @res > 20;
print header, start_html("Auswahl nach Straßen und Orten"), h1("Auswahl nach Straßen und Orten");
print h2("Mehrere Orte gefunden");
_form;
print radio_group
(-name=>"coords",
-values => [map { $_->[Strassen::COORDS()]->[0] } @res],
-labels => {map { my $n = $_->[Strassen::NAME()];
$n =~ s/\|/ /;
($_->[Strassen::COORDS()]->[0] => $n)
} @res},
-linebreak => "true",
), br;
print submit(-value => "Zeigen");
print end_form, hr;
show_form();
print end_html;
}
}
sub resolve_fulltext {
require Strassen::Core;
require File::Basename;
my $STRASSEN_FILE = Strassen::LAST() + 1;
my $STRASSEN_CENTER = Strassen::LAST() + 2;
my $STRASSEN_LABEL = Strassen::LAST() + 3;
my $STRASSEN_ICON = Strassen::LAST() + 4;
my $STRASSEN_ICONS = Strassen::LAST() + 5;
# heurstic to find data directory
my $dir;
for my $try_dir (@Strassen::datadirs, @INC) {
if (-e "$try_dir/strassen") {
$dir = $try_dir;
last;
}
}
if (!defined $dir) {
die "Cannot find data directory in @INC";
}
my @res;
my @files = grep { -f $_ }
grep { !/(relation_gps|coords\.data|ampelschaltung|-orig|-info|~|\.st|\.desc|RCS|CVS)$/ }
glob("$dir/*");
die "No files in directory $dir" if !@files; # should not happen
my @cmd = ("fgrep", "-i", "--", param("searchterm"), @files);
#warn "Cmd: @cmd\n";
open(GREP, "-|") or do {
require File::Spec;
open(STDERR, ">" . File::Spec->devnull)
or warn "Can't redirect stderr to /dev/null: $!";
exec @cmd;
die $!; # XXX actually not visible because of redirect
};
while() {
my($file, $line) = split /:/, $_, 2;
my($ret) = Strassen::parse($line);
if ($ret->[Strassen::COORDS()] && @{$ret->[Strassen::COORDS()]}) {
$ret->[$STRASSEN_FILE] = File::Basename::basename($file);
$ret->[$STRASSEN_CENTER] = $ret->[Strassen::COORDS()]->[$#{$ret->[Strassen::COORDS()]}/2];
$ret->[$STRASSEN_LABEL] = file_to_label($ret->[$STRASSEN_FILE]);
$ret->[$STRASSEN_ICON] = file_to_icon($ret->[$STRASSEN_FILE]);
push @res, $ret;
}
}
close GREP;
if (!@res) {
print header, start_html("Auswahl nach Straßen und Orten"), h1("Auswahl nach Straßen und Orten");
print "Nichs gefunden!
";
show_form();
print end_html;
} elsif (@res > 1) {
my @new_res;
my %seen;
for my $element (@res) {
my $e = $element;
if (!exists $seen{$e->[$STRASSEN_CENTER]}) {
push @new_res, $e;
$seen{$e->[$STRASSEN_CENTER]} = $#new_res;
$e->[$STRASSEN_ICONS] = [];
} else {
$e = $new_res[$seen{$element->[$STRASSEN_CENTER]}];
}
if (defined $element->[$STRASSEN_ICON]) {
push @{ $e->[$STRASSEN_ICONS] }, $element->[$STRASSEN_ICON];
}
last if @new_res > 40;
}
@res = @new_res;
if (@res > 1) {
print header, start_html("Auswahl nach Straßen und Orten"), h1("Auswahl nach Straßen und Orten");
print h2("Mehrere Treffer");
_form;
{
my $use_icons = 1;
my $values = [map { $_->[$STRASSEN_CENTER] }
sort { lc $a->[Strassen::NAME()] cmp lc $b->[Strassen::NAME()]}
@res];
my $labels = {map { my $n = $_->[Strassen::NAME()];
$n =~ s/\|/ /;
$n .= " (" . $_->[$STRASSEN_LABEL] . ")";
($_->[$STRASSEN_CENTER] => $n)
} @res};
my $icons = {map { my $n = "";
my @icons = @{ $_->[$STRASSEN_ICONS] };
if (@icons && $use_icons) {
for my $icon (@icons) {
$n .= qq(
);
}
}
($_->[$STRASSEN_CENTER] => $n)
} @res};
my $name = "coords";
if (!$use_icons) {
print radio_group
(-name=>$name,
-values => $values,
-labels => $labels,
-linebreak => "true",
), br;
} else {
print start_table;
for my $value (@$values) {
print qq( | $labels->{$value} | $icons->{$value} |
);
}
print end_table;
}
}
print submit(-value => "Zeigen");
print end_form, hr;
show_form();
print end_html;
}
}
if (@res == 1) {
my $xy = $res[0]->[Strassen::COORDS()]->[0];
redirect_to_map($xy);
}
}
sub resolve_latlong {
my($lat, $long) = @_;
require Karte;
$Karte::Polar::obj = $Karte::Polar::obj; # cease -w
Karte::preload("Standard", "Polar");
my($x, $y) = map { int } $Karte::Polar::obj->map2standard($long, $lat);
redirect_to_map("$x,$y");
}
sub redirect_to_map {
my($coord, %args) = @_;
my $usemap = param("usemap") || "mapserver";
if ($usemap eq 'googlemaps') {
redirect_to_googlemaps($coord, %args);
} else {
redirect_to_ms($coord, %args);
}
}
sub redirect_to_googlemaps {
my($coord, %args) = @_;
my $q2 = CGI->new({wpt_or_trk => "!$coord"});
# XXX do not hardcode
print redirect("http://www.radzeit.de/cgi-bin/bbbikegooglemap.cgi?" . $q2->query_string);
return;
}
sub redirect_to_ms {
my($coord, %args) = @_;
if (!$args{-scope}) {
$args{-scope} = scope(split /,/, $coord);
}
$args{-scope} = "all," . $args{-scope};
if (param("mapext")) {
my($x1,$y1,$x2,$y2) = split /\s+/, param("mapext");
$args{-width} = $x2-$x1;
$args{-height} = $y2-$y1;
} elsif (param("width")) {
$args{-width} = param("width");
$args{-height} = (param("height") ? param("height") : $args{-width});
} else {
if ($args{-scope} eq 'city') {
@args{qw(-width -height)} = (2000, 2000);
} elsif ($args{-scope} eq 'region') {
@args{qw(-width -height)} = (5000, 5000);
} else {
@args{qw(-width -height)} = (8000, 8000);
}
}
if (param("layer")) {
$args{-layers} = [param("layer")];
} else {
$args{-layers} = [qw(bahn flaechen gewaesser
faehren route grenzen orte)] if !$args{-layers};
}
require File::Basename;
$args{-bbbikeurl} = File::Basename::dirname(url) . "/bbbike.cgi";
require BBBikeMapserver;
my $ms = BBBikeMapserver->new;
$ms->read_config("$FindBin::RealBin/bbbike.cgi.config");
$ms->set_coords($coord) if $coord;
$ms->{CGI} = CGI->new;
$ms->start_mapserver(%args);
}
# values from ..../data/Makefile
sub scope {
my($x,$y) = @_;
my @scopes = ([-15700,31300,37300,-8800],
[-80800,81600,108200,-86200],
);
for my $i (0 .. $#scopes) {
if ($x > $scopes[$i]->[0] &&
$x < $scopes[$i]->[2] &&
$y > $scopes[$i]->[3] &&
$y < $scopes[$i]->[1]) {
if ($i == 0) {
return "city";
} else {
return "region";
}
}
}
"wideregion";
}
sub file_to_label {
my $file = shift;
# XXX do not hardcode
my %map =
(
'Berlin.coords.data' => 'Berliner Koordinaten',
'Berlin_and_Potsdam.coords.data' => 'Berliner und Potsdamer Koordinaten',
'Potsdam.coords.data' => 'Potsdamer Koordinaten',
ampeln => 'Ampeln',
ampelschaltung => 'Ampelschaltungen',
berlin => 'Grenzen von Berlin',
comments => 'Kommentare',
deutschland => 'Grenzen von Deutschland',
faehren => 'Fähren',
flaechen => 'Flächen (Parks, Wälder, Flughäfen ...)',
gesperrt => 'Gesperrte und Einbahnstraßen',
gesperrt_car => 'Gesperrte Straßen für motorisierten Verkehr',
green => 'Grüne Wege',
handicap_l => 'Sonstige Behinderungen (Landstraßen)',
handicap_s => 'Sonstige Behinderungen (Stadtstraßen)',
hoehe => 'Höhenpunkte',
housenumbers => 'Hausnummern',
innerberliner_grenze => 'Innerberliner Grenze',
kinos => 'Kinos',
kneipen => 'Kneipen',
label => 'Labels', # XXX
landstrassen => 'Landstraßen',
landstrassen2 => 'Landstraßen (jwd)',
nolighting => 'Stadtstraßen ohne Beleuchtung',
orte => 'Orte',
orte2 => 'Orte (jwd)',
orte_city => 'Besondere Bezirke in Berlin',
plaetze => 'Plätze',
plz => 'Postleitzahlgebiete',
potsdam => 'Grenzen von Potsdam',
qualitaet_l => 'Straßenqualität (Landstraßen)',
qualitaet_s => 'Straßenqualität (Stadtstraßen)',
radwege => 'Radwege, Busspuren, verkehrsberuhigte Bereiche',
radwege_exact => 'Radwege (exakte Koordinaten)',
rbahn => 'Regionalbahnlinien',
rbahnhof => 'Regionalbahnhöfe',
relation_gps => 'Relationen zu GPS-Punkten',
sbahn => 'S-Bahnlinie',
sbahnhof => 'S-Bahnhof',
sbahnhof_bg => 'behindertenfreundliche Zugänge an S-Bahnhöfen',
sehenswuerdigkeit => 'Sehenswürdigkeiten, öffentliche Gebäude',
strassen => 'Stadtstraßen',
strassen_b_and_p => 'Stadtstraßen in Berlin und Potsdam',
ubahn => 'U-Bahnlinien',
ubahnhof => 'U-Bahnhöfe',
ubahnhof_bg => 'behindertenfreundliche Zugänge an U-Bahnhöfen',
vorfahrt => 'abknickende Vorfahrtsstraßen',
wasserstrassen => 'Gewässer in Berlin',
wasserumland => 'Gewässer im Umland',
wasserumland2 => 'Gewässer jwd',
);
exists $map{$file} ? $map{$file} : $file;
}
sub file_to_icon {
my $file = shift;
# XXX do not hardcode
my %map =
(
ampeln => 'ampel',
ampelschaltung => 'ampel',
berlin => 'berlin_overview_small',
faehren => 'ferry',
flaechen => 'flaechen',
gesperrt => 'legend_blocked',
gesperrt_car => 'legend_blocked',
kinos => 'kino_klein',
kneipen => 'glas',
landstrassen => 'landstrasse',
landstrassen2 => 'landstrasse',
orte => 'ort',
orte2 => 'ort',
qualitaet_l => 'kopfstein_klein',
qualitaet_s => 'kopfstein_klein',
rbahn => 'rbahn',
rbahnhof => 'rbahn',
sbahn => 'sbahn',
sbahnhof => 'sbahn',
sbahnhof_bg => 'behindertenfreundlich',
sehenswuerdigkeit => 'star',
strassen => 'strasse',
strassen_b_and_p => 'strasse',
ubahn => 'ubahn',
ubahnhof => 'ubahn',
ubahnhof_bg => 'behindertenfreundlich',
vorfahrt => 'vorfahrt',
wasserstrassen => 'wasser',
wasserumland => 'wasser',
wasserumland2 => 'wasser',
);
exists $map{$file} ? $map{$file} . ".gif" : undef;
}
# No __END__ !
=comment
Calling example:
http://?coords=5775,11631;layer=bahn;layer=flaechen;layer=route;layer=gewaesser;layer=sehenswuerdigkeit;width=2000
=cut