source: subversion/applications/rendering/osmAtHome/osmAtHome.pl @ 6704

Last change on this file since 6704 was 2193, checked in by jdschmidt, 13 years ago

updated with Osmarender4 and beziercurvehinting

  • Property svn:executable set to *
File size: 9.7 KB
Line 
1#!/usr/bin/perl
2use LWP::Simple;
3use File::Copy;
4#-----------------------------------------------------------------------------
5# OpenStreetMap @ Home
6#
7# This program will:
8# - get a request from the almien website for a map that needs rendering
9# - render it, using tools such as xmlstarlet and inkscape on your computer
10# - upload the result to the almien website, for public display
11#
12# This program will use considerable amounts of system resource (cpu, memory, disk)
13# It is designed for use by a few trusted users, who will create maps and not
14# upload malicious data.  Hence, the script includes a password which is required
15# to upload the resultant map back to the almien website.
16#
17# You can run this program without a password, and it will render maps from
18# OSM data and save them on your disk.
19#
20# Contact OJW on the Openstreetmap wiki for help using this program
21#-----------------------------------------------------------------------------
22# Copyright 2006, Oliver White
23#
24# This program is free software; you can redistribute it and/or
25# modify it under the terms of the GNU General Public License
26# as published by the Free Software Foundation; either version 2
27# of the License, or (at your option) any later version.
28#
29# This program is distributed in the hope that it will be useful,
30# but WITHOUT ANY WARRANTY; without even the implied warranty of
31# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32# GNU General Public License for more details.
33#
34# You should have received a copy of the GNU General Public License
35# along with this program; if not, write to the Free Software
36# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
37#-----------------------------------------------------------------------------
38# Prerequisites for the program :
39# Perl
40# xmlstarlet
41# inkscape
42# perlmodules LWP::Simple, File::Copy and Math::Vec. First two modules are
43# normally included in a standard perl installation, and the latter module
44# can be installed via CPAN (or PPM on Windows). Debian users can also
45# install the latter module with this command : "apt-get install libmath-vec-perl"
46#
47#------------------------------------------------------------------------------
48my $Password = "user|password";  # Ask OJW for a password to use this script
49
50my $args = shift;
51if($args eq "-h") {
52        print "OpenStreetMap @ Home Client\n\n";
53        print "You will need a username and password for the almien site to participate.\n";
54        print "See http://wiki.openstreetmap.org/index.php/OSM%40home for details\n";
55        exit 1;
56}
57
58# Process
59UpdateOsmarender();
60while(1){
61ProcessRequestFromWeb($Password);
62sleep(60);
63};
64exit;
65
66#-----------------------------------------------------------------------------
67# Gets latest copy of osmarender from repository
68#-----------------------------------------------------------------------------
69sub UpdateOsmarender(){
70  foreach $File(("osm-map-features.xml", "osmarender.xsl", "Osm_linkage.png", "somerights20.png")){
71 
72    DownloadFile(
73    "http://svn.openstreetmap.org/utils/osmAtHome/$File",
74    $File,
75    1,
76    "Osmarender ($File)");
77  }
78}
79
80#-----------------------------------------------------------------------------
81# Gets a request from almien for a map that needs rendering, and does it
82#-----------------------------------------------------------------------------
83sub ProcessRequestFromWeb(){
84  my ($Password) = @_;
85  DownloadFile(
86    "http://almien.co.uk/OSM/Places/?action=random", 
87    "random.txt",
88    0,
89    "Rendering requests");
90 
91  ProcessRequest("random.txt", $Password);
92}
93
94#-----------------------------------------------------------------------------
95# Processes a textfile containing request for a map-rendering
96#-----------------------------------------------------------------------------
97sub ProcessRequest(){
98  my ($File, $Password) = @_;
99 
100  # File comprises pipe-separated fields
101  open(IN, "<", $File);
102  my ($Version, $ID, $Width, $URL) = split(/\|/, <IN>);
103  close IN;
104 
105  if($Version != 2){
106    print STDERR "A new version of this script is available\n";
107    print STDERR "Not processing requests, as the interface may have changed\n";
108    print STDERR "Please download latest script and run that instead of this one\n";
109    exit;
110  }
111  if($ID == -1){ 
112    print STDERR "Nothing to do!\nSleeping for 1 hour : press Ctrl-C to quit\n";
113    sleep(3600);
114#    exit 1;
115    return;
116 }
117 
118#  UpdateOsmarender();
119 
120  print STDERR "Using interface version $Version\n";
121  print STDERR "Downloading $ID from $URL\n";
122 
123  foreach $OldFile("output.png", "output.svg", "data.osm"){
124    unlink $OldFile if(-f $OldFile);
125  }
126 
127  # Get the OSM data
128  DownloadFile($URL, "data.osm.gz", 0, "OSM data for location (ID $ID)");
129  # Decompress data
130  `gunzip data.osm.gz`;
131 
132  # Transform it to SVG
133  xml2svg("output.svg");
134 
135  # Render it to PNG
136  svg2png("output.svg", "output.png", $Width);
137
138  # Upload it
139  upload("output.png", $ID, $Password);
140 
141  # Say where to find the result
142  print "Done. View the result at\nhttp://almien.co.uk/OSM/Places/?id=$ID\n";
143}
144
145#-----------------------------------------------------------------------------
146#
147#-----------------------------------------------------------------------------
148sub DownloadFile(){
149  my ($URL, $File, $UseExisting, $Title) = @_;
150 
151  print STDERR "Downloading: $Title...";
152 
153  if($UseExisting){
154    mirror($URL, $File);
155    }
156  else{
157    getstore($URL, $File);
158    }
159 
160  printf STDERR " done, %d bytes\n", -s $File;
161 
162}
163
164#-----------------------------------------------------------------------------
165# Transform an OSM file (using osmarender) into SVG
166#-----------------------------------------------------------------------------
167sub xml2svg(){
168  my($SVG) = @_;
169  my($TSVG) = "temp.svg";
170  my $Cmd = sprintf("%sxmlstarlet tr %s %s > %s",
171    "nice ", # Blank this out for use on windows
172    "osmarender.xsl",
173    "osm-map-features.xml",
174    $TSVG);
175  print STDERR "Transforming...";
176  `$Cmd`;
177#-----------------------------------------------------------------------------
178# Process lines to bezier
179#-----------------------------------------------------------------------------
180  my $Cmd = sprintf("%s ./lines2curves.pl %s > %s",
181     "nice ",
182     $TSVG,
183     $SVG);
184  print STDERR "Lines to Bezier..";
185  `$Cmd`;
186#------------------------------------------------------------------------------
187# Quickfix in case lines2curves found a zerolenght segment
188#------------------------------------------------------------------------------ 
189  my $filesize = -s "output.svg";
190  if (!$filesize) {
191  copy($TSVG,$SVG);
192  print STDERR "zerolenght segment, no bezier hinting. Rendering without bezier hinting.\n";
193    } 
194  print STDERR " done\n";
195}
196
197#-----------------------------------------------------------------------------
198# Render a SVG file
199#-----------------------------------------------------------------------------
200sub svg2png(){
201  my($SVG, $PNG, $Size) = @_;   
202  my $Cmd = sprintf("%sinkscape -w %d -D -b FFFFFF -e %s %s", 
203    "nice ", # Blank this out for use on windows
204    $Size,
205    $PNG, 
206    $SVG);
207  print STDERR "Rendering...";
208  `$Cmd`;
209  print STDERR " done\n";
210}
211
212
213#-----------------------------------------------------------------------------
214# Upload a rendered map to almien
215#-----------------------------------------------------------------------------
216sub upload(){
217  my ($File, $ID, $Password) = @_;
218  $URL = "http://almien.co.uk/OSM/Places/upload.php";
219 
220  my $ua = LWP::UserAgent->new(env_proxy => 0,
221    keep_alive => 1,
222    timeout => 60);
223  $ua->protocols_allowed( ['http'] );
224  $ua->agent("OsmAtHome");
225
226  my $res = $ua->post($URL,
227    Content_Type => 'form-data',
228    Content => [ file => [$File], id => $ID, mp => $Password ]);
229   
230  if(!$res->is_success()){
231    die("Post error: " . $res->error);
232  } 
233}
234
235#-----------------------------------------------------------------------------
236# Modifying this script:
237#
238# You probably won't have the exact same setup as me, so this script might need
239# some changes to work properly.  Since I only expect a handful of people to run
240# this script, I think they can probably modify it themselves to suit their
241# computer's configuration.  Here's some of the things to look at:
242#
243# Location of inkscape - I've just called it "inkscape", but you can change that to
244# the path of your inkscape program if it's elsewhere
245#
246# Location of xmlstarlet - on Windows, it's c:\xml\xml.exe by default, so change that
247#
248# "Nice" statements - the script uses the nice keyword to give the rendering
249# low scheduling priority, so it doesn't lock-up your computer and stop your desktop
250# working.  Remove this on Windows, as it won't work
251#
252# Other SVG->PNG renderers - careful, as many renderers don't render the same area of
253# the SVG.  It would probably be a good idea if we all used inkscape, as that makes the
254# generated images much more predictable in terms of where the edges are exactly.
255#
256# Other XSLT programs - this is easier, as you can pick any one.  I've used xmlstarlet,
257# but other people prefer xsltproc, xalan, etc.  If you use a different program,
258# you'll need to update the command-line options this script supplies, so that
259# it does the right thing.
260#
261#-----------------------------------------------------------------------------
262# Testing:
263#
264# To test changes to this script without affecting other users, simply comment-out
265# the upload() function call, so that renders things and leaves them on your
266# computer, rather than trying to upload the result.
267#
268# To test the effect of changes to the osmarender files, comment-out the
269# UpdateOsmarender() function call, so that it keeps your modified version of
270# osmarender, instead of downloading a new copy each time.
271#
272# To render a particular town, look-up the town's ID at almien.co.uk/OSM/Places,
273# then hardcode that ID in the script rather than downloading IDs from the web
274#-----------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.