From: Michael 'PoempelFox' Meier Date: Fri, 31 Jul 2015 14:03:57 +0000 (+0200) Subject: now with cgi-mode and lots of other improvements. X-Git-Url: http://git.rrze.uni-erlangen.de/gitweb/?p=osmrrze.git;a=commitdiff_plain;h=9de6d037443b06450b73b76188dc9831c5a4004c now with cgi-mode and lots of other improvements. --- diff --git a/scripts/osmbuildings-json-generator.pl b/scripts/osmbuildings-json-generator.pl index 0d6c9d8..16ad1c3 100755 --- a/scripts/osmbuildings-json-generator.pl +++ b/scripts/osmbuildings-json-generator.pl @@ -51,16 +51,55 @@ sub fetchlastofhr($$@) { return $res; } +# Helper functions for the CGI variant. Taken from the openstreetmap-Wiki. +use Math::Trig; +sub Project { + my ($X, $Y, $Zoom) = @_; + my $Unit = 1 / (2 ** $Zoom); + my $relY1 = $Y * $Unit; + my $relY2 = $relY1 + $Unit; + + # note: $LimitY = ProjectF(degrees(atan(sinh(pi)))) = log(sinh(pi)+cosh(pi)) = pi + # note: degrees(atan(sinh(pi))) = 85.051128.. + #my $LimitY = ProjectF(85.0511); + + # so stay simple and more accurate + my $LimitY = pi; + my $RangeY = 2 * $LimitY; + $relY1 = $LimitY - $RangeY * $relY1; + $relY2 = $LimitY - $RangeY * $relY2; + my $Lat1 = ProjectMercToLat($relY1); + my $Lat2 = ProjectMercToLat($relY2); + $Unit = 360 / (2 ** $Zoom); + my $Long1 = -180 + $X * $Unit; + return ($Lat2, $Long1, $Lat1, $Long1 + $Unit); # S,W,N,E +} +sub ProjectMercToLat($){ + my $MercY = shift; + return rad2deg(atan(sinh($MercY))); +} +sub ProjectF +{ + my $Lat = shift; + $Lat = deg2rad($Lat); + my $Y = log(tan($Lat) + sec($Lat)); + return $Y; +} + # ---------------------------------------------------------------------------- # main() # ---------------------------------------------------------------------------- +$iscgi = 0; + # Parse commandline foreach $a (@ARGV) { if ($a eq '-q') { $verblev--; } elsif ($a eq '-v') { $verblev++; + } elsif ($a eq '--cgi') { + $iscgi = 1; } else { print("Unknown parameter: $a\n"); print("Syntax: $0 [-q] [-v]\n"); @@ -69,6 +108,22 @@ foreach $a (@ARGV) { } } +if (defined($ENV{'REQUEST_URI'})) { + $iscgi = 1; + print("Content-type: application/json\n\n"); + unless ($ENV{'REQUEST_URI'} =~ m!(\d+)/(\d+)/(\d+)\.json$!) { + print("{\n\"_comment\": \"Sorry, query parameters not understood.\"\n}\n"); + exit(0); + } + my $cgiz = int($1); my $cgix = int($2); my $cgiy = int($3); + #print("DEBUG: z=$cgiz x=$cgix y=$cgiy\n"); + if ($cgiz < 15) { + print("{\n\"_comment\": \"No data will be returned at this zoom level.\"\n}\n"); + } + ($y1, $x1, $y2, $x2) = Project($cgix, $cgiy, $cgiz); + #print("DEBUG: mapped to ($x1 $y1) ($x2 $y2)\n"); +} + unless ($dbh = DBI->connect("dbi:Pg:dbname=$dbname","","")) { print(STDERR "Failed to open database. Please try again later.\n"); exit(1); } @@ -78,43 +133,73 @@ $ty1 = $dbh->selectrow_array("select ST_Y(ST_transform(ST_GeomFromText('POINT($x $tx2 = $dbh->selectrow_array("select ST_X(ST_transform(ST_GeomFromText('POINT($x2 $y2)', 4326), 900913))"); $ty2 = $dbh->selectrow_array("select ST_Y(ST_transform(ST_GeomFromText('POINT($x2 $y2)', 4326), 900913))"); my $cntr = 0; -print("// Note: this file has been autogenerated by $0\n"); -print("var FAUGeoJSON = {\n"); +if ($iscgi == 0) { + print("// Note: this file has been autogenerated by $0\n"); + print("var FAUGeoJSON = {\n"); +} else { + print("{\n"); +} print(" \"type\": \"FeatureCollection\",\n"); print(" \"features\": [\n"); -foreach $table ('planet_osm_line', 'planet_osm_polygon') { +foreach $xtable ('planet_osm_polygon1', 'planet_osm_polygon2', 'planet_osm_line') { # 'planet_osm_polygon', 'planet_osm_line' + my $querypart1 = " ((tags->'building:part') is not null)"; + my $table = 'planet_osm_polygon'; + if ($xtable eq 'planet_osm_polygon1') { + $querypart1 = " (building is not null)"; + } elsif ($xtable eq 'planet_osm_line') { + $table = $xtable; + } + # Note: && in this case is the postgis operator for 'bounding box overlaps'. my $sth = $dbh->prepare("select osm_id, way, building, 'tower:type', name, tags" - . " from $table where" - . " (building is not null or (tags->'building:part') is not null)" - . " and way && ST_MakeEnvelope($tx1, $ty1, $tx2, $ty2)"); + . " from $table where $querypart1" + . " and (way && ST_MakeEnvelope($tx1, $ty1, $tx2, $ty2))"); unless ($sth->execute()) { - print(STDERR "Sorry, database query exploded.!\n"); + print(STDERR "Sorry, database query blew up.!\n"); exit(1); } my $sth2 = $dbh->prepare("select ST_X(points) as x, ST_Y(points) as y" . " from (select ST_astext((ST_dumppoints(ST_transform(?, 4326))).geom) as points) as points"); while ($row = $sth->fetchrow_hashref()) { + if ($xtable eq 'planet_osm_polygon1') { + my $hassubparts = $dbh->selectrow_array("select count(*)" + . " from planet_osm_line" + . " where ((tags->'building:part') is not null)" + . " and (ST_Covers(" . $dbh->quote($row->{'way'}) . ", way) = true)"); + # The subparts usually cover the whole building, so we do NOT draw the + # whole building but only the subparts. + if ($hassubparts > 0) { next; } + } my $hstoredec; if (defined($row->{'tags'})) { $hstoredec = Pg::hstore::decode($row->{'tags'}); } - my $height = fetchlastofhr(1, $hstoredec, 'levels', 'building:levels'); - $height = $height * 2.5; - $height = fetchlastofhr($height, $hstoredec, 'height', 'building:height'); - $height = sprintf("%.1f", $height); - my $minheight = fetchlastofhr(0, $hstoredec, 'min_levels', 'building:min_levels'); - $minheight = $minheight * 2.5; - $minheight = fetchlastofhr($minheight, $hstoredec, 'min_height', 'building:min_height'); - $minheight = sprintf("%.1f", $minheight); + my $levels = fetchlastofhr(1, $hstoredec, 'levels', 'building:levels'); + my $height = fetchlastofhr($height, $hstoredec, 'height', 'building:height'); + unless ($height =~ m/^[0-9.]+$/) { undef($height); } + my $minlevel = fetchlastofhr(0, $hstoredec, + 'min_levels', 'building:min_levels', 'min_level', 'building:min_level'); + my $minheight = fetchlastofhr($minheight, $hstoredec, 'min_height', 'building:min_height'); + unless ($minheight =~ m/^[0-9.]+$/) { undef($minheight); } my $wallcolor = fetchlastofhr(undef, $hstoredec, 'building:color', 'building:colour'); my $roofcolor = fetchlastofhr(undef, $hstoredec, 'roof:color', 'roof:colour', 'building:roof:color', 'building:roof:colour'); my $roofshape = fetchlastofhr(undef, $hstoredec, 'roof:shape', 'building:roof:shape'); my $roofheight = fetchlastofhr(undef, $hstoredec, 'roof:height', 'building:roof:height'); + if ($cntr != 0) { + print(",\n"); + } $cntr++; print(" {\n"); print(" \"type\": \"Feature\",\n"); - print(" \"id\": $cntr,\n"); + if (defined($row->{'osm_id'})) { + print(" \"id\": " . $row->{'osm_id'} . ",\n"); + } else { + print(" \"id\": $cntr,\n"); + } + if (defined($row->{'name'})) { + $row->{'name'} =~ s/"//g; + print(" \"name\": \"" . $row->{'name'} . "\",\n"); + } print(" \"geometry\": {\n"); print(" \"type\": \"Polygon\",\n"); print(" \"coordinates\": [[\n"); @@ -123,34 +208,58 @@ foreach $table ('planet_osm_line', 'planet_osm_polygon') { exit(1); } my ($onex, $oney); + my $firstcoord = 1; while (($onex, $oney) = $sth2->fetchrow_array()) { - print(" [ $onex, $oney ],\n"); + if ($firstcoord == 1) { + $firstcoord = 0; + } else { + print(",\n"); + } + printf(" [ %.5f, %.5f ]", $onex, $oney); } + print("\n"); print(" ]]\n"); print(" },\n"); print(" \"properties\": {\n"); - print(" \"height\": $height,\n"); - print(" \"min_height\": $minheight,\n"); + if (defined($height)) { + print(" \"height\": $height,\n"); + } + if (defined($min_height)) { + print(" \"min_height\": $minheight,\n"); + } + if (defined($levels)) { + print(" \"levels\": $levels,\n"); + } + if (defined($minlevel)) { + print(" \"minLevel\": $minlevel,\n"); + } if (defined($wallcolor)) { print(" \"wallColor\": \"$wallcolor\",\n"); } if (defined($roofcolor)) { + $roofcolor =~ s/"//g; print(" \"roofColor\": \"$roofcolor\",\n"); } if (defined($roofshape)) { + $roofshape =~ s/"//g; print(" \"roofShape\": \"$roofshape\",\n"); } if (defined($roofheight)) { $roofheight = sprintf("%.1f", $roofheight); print(" \"roofHeight\": \"$roofheight\",\n"); } + print(" \"dummy\": \"void\"\n"); print(" }\n"); - print(" },\n"); + print(" }"); } $sth2->finish(); undef($sth2); $sth->finish(); undef($sth); } -print(" ]\n"); -print("};\n"); +print("\n ]\n"); +if ($iscgi == 0) { + print("};\n"); +} else { + print("}\n"); +}