source: subversion/applications/utils/osm-extract/polygons/polyconvert.pl @ 26630

Revision 26630, 7.1 KB checked in by zverik, 3 years ago (diff)

fix poly2gpx

Line 
1#!/usr/bin/perl
2
3# This converts *.poly into *.osm or *.gpx or *.wkt and back.
4# Can work as a CGI script, format=osm/gpx/wkt (default osm), source: content or file
5# Replaces (and is based on) poly2osm.pl, poly2wkt.pl, poly2bb.pl, gpx2poly.pl, osm2poly.pl
6#
7# written by Ilya Zverev <zverik@textual.ru>, public domain.
8# installed at http://textual.ru/poly/
9
10use strict;
11use CGI;
12
13my $iscgi = defined($ENV{'REQUEST_METHOD'});
14my $cgi = CGI->new if $iscgi;
15
16my $to = $iscgi ? $cgi->param('format') || 'osm' : 'osm';
17
18my $contents;
19my $tmpseparator = $/;
20undef $/;
21if( $iscgi ) {
22        my $handle  = $cgi->upload('file');
23        $contents = defined($handle) ? <$handle> : $cgi->param('content');
24} else {
25        $contents = <>;
26}
27$/ = $tmpseparator;
28error("Empty input file") if $contents =~ /^\s*$/;
29$contents =~ s/\r//g;
30
31my $result;
32my $ext;
33if( $contents =~ /END\s+END\s*$/ ) {
34        # poly
35        if( $to eq 'osm' ) { $result = poly2osm($contents); $ext = 'osm'; }
36        elsif( $to eq 'gpx' || $to eq 'ol' ) { $result = poly2gpx($contents); $ext = 'gpx'; }
37        elsif( $to eq 'wkt' ) { $result = poly2wkt($contents); $ext = 'wkt'; }
38        else { error("Unknown format $to"); }
39}
40elsif( $contents =~ /^MULTIPOLYGON/ ) {
41        $result = wkt2poly($contents);
42        $ext = 'poly';
43}
44elsif( $contents =~ /\<gpx.+\<trkpt/s ) {
45        $result = gpx2poly($contents);
46        $ext = 'poly';
47}
48elsif( $contents =~ /\<osm.+\<node/s ) {
49        $result = osm2poly($contents);
50        $ext = 'poly';
51}
52else { error("Unknown format of input file"); }
53
54if( $to eq 'ol' ) {
55        error("Source file must be poly or gpx") if $result !~ /\<gpx/ && $contents !~ /\<gpx/;
56        $result = openlayers($result =~ /\<gpx/ ? $result : $contents);
57        print "Content-type: text/html\n\n" if $iscgi;
58} else {
59        print "Content-Disposition: attachment; filename=result.$ext\n\n" if $iscgi;
60}
61print $result;
62
63sub error {
64        my($error) = @_;
65        die($error) if !$iscgi;
66        print "Content-type: text/html\n\nError: <b>$error</b><br>Sorry.";
67        exit;
68}
69
70# Worker subs. Input: the whole file as string. Returns resulting file as string.
71
72sub poly2gpx {
73        my @contents = split /^/, $_[0];
74        my $pos = 0;
75        # first line
76        # (employ workaround for polygon files without initial text line)
77        my $poly_file = $contents[$pos++]; chomp($poly_file);
78        my $workaround = 0;
79        if ($poly_file =~ /^\d+$/)
80        {
81                $workaround=$poly_file;
82                $poly_file="none";
83        }
84
85        my $tracks;
86
87        while(1)
88        {
89                my $poly_id = $workaround || $contents[$pos++];
90                chomp($poly_id);
91                last if ($poly_id =~ /^END/); # end of file
92               
93                $tracks .= "<trk>\n<name>$poly_file $poly_id</name>\n<trkseg>\n";       
94
95                while(my $line = $contents[$pos++])
96                {
97                        last if ($line =~ /^END/); # end of poly
98                        my ($dummy, $x, $y) = split(/\s+/, $line);
99                        $tracks .= sprintf("  <trkpt lat=\"%f\" lon=\"%f\">\n  </trkpt>\n", $y, $x);
100                }
101                $tracks .= "</trkseg>\n</trk>\n";       
102                $workaround=0;
103        }
104
105        return "<?xml version='1.0' encoding='UTF-8'?>\n<gpx version=\"1.1\" creator=\"polyconvert.pl\" xmlns=\"http://www.topografix.com/GPX/1/1\" ".
106    "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n".
107        "$tracks</gpx>";
108}
109
110sub poly2wkt {
111        my @contents = split /^/, $_[0];
112        my $pos = 0;
113        # first line
114        # (employ workaround for polygon files without initial text line)
115        my $poly_file = $contents[$pos++]; chomp($poly_file);
116        my $workaround = 0;
117        if ($poly_file =~ /^\d+$/)
118        {
119                $workaround=$poly_file;
120                $poly_file="none";
121        }
122
123        my $polygons;
124
125        while(1)
126        {
127                my $poly_id = $workaround || $contents[$pos++];
128                chomp($poly_id);
129                last if ($poly_id =~ /^END/); # end of file
130                my $coords;
131
132                while(my $line = $contents[$pos++])
133                {
134                        last if ($line =~ /^END/); # end of poly
135                        my ($dummy, $x, $y) = split(/\s+/, $line);
136                        push(@$coords, sprintf("%f %f", $x, $y));
137                }
138                push(@$polygons, "((".join(",", @$coords)."))");
139                $workaround=0;
140        }
141
142        return "MULTIPOLYGON(".join(",",@$polygons).")\n";
143}
144
145sub poly2osm {
146        my @contents = split /^/, $_[0];
147        my $pos = 0;
148        my %nodehash;
149
150        # first line
151        # (employ workaround for polygon files without initial text line)
152        my $poly_file = $contents[$pos++]; chomp($poly_file);
153        my $workaround = 0;
154        if ($poly_file =~ /^\d+$/)
155        {
156                $workaround=$poly_file;
157                $poly_file="none";
158        }
159
160        my $nodecnt = -1;
161        my $waycnt = -1;
162
163        my $nodes;
164        my $ways;
165        my $note = "    <tag k='note' v='created by poly2osm.pl from a polygon file. not for uploading!' />\n";
166        my $line;
167
168        while(1) {
169                my $poly_id;
170                if ($workaround==0) {
171                   $poly_id=$contents[$pos++];
172                } else {
173                   $poly_id=$workaround;
174                }
175                chomp($poly_id);
176                my $startnode = $nodecnt;
177                last if ($poly_id =~ /^END/); # end of file
178
179                $ways .= sprintf("  <way id='%d'>\n    <tag k='polygon_id' v='%d' />\n    <tag k='polygon_file' v='%s' />\n",
180                        $waycnt--, $poly_id, $poly_file);
181                $ways .= $note;
182
183                while($line = $contents[$pos++])
184                {
185                        last if ($line =~ /^END/); # end of poly
186                        my ($dummy, $x, $y) = split(/\s+/, $line);
187                        my $existingnode = $nodehash{"$x|$y"};
188                        if (defined($existingnode))
189                        {
190                                $ways .= sprintf("    <nd ref='%d' />\n", $existingnode);
191                        }
192                        else
193                        {
194                                $nodehash{"$x|$y"} = $nodecnt;
195                                $ways .= sprintf("    <nd ref='%d' />\n", $nodecnt);
196                                $nodes .= sprintf("  <node id='%d' lat='%f' lon='%f' />\n", $nodecnt--, $y, $x);
197                        }
198                }
199                $ways .= "  </way>\n";
200                undef $workaround;
201        };
202        return "<osm generator='osm2poly.pl' version='0.5'>\n$nodes$ways</osm>\n";
203}
204
205sub gpx2poly {
206        my @contents = split /^/, $_[0];
207        my $pos = 0;
208        my $poly_id = -1;
209        my $poly_file;
210        my $polybuf;
211        my $outbuf;
212        my $id=0;
213
214        while($pos <= $#contents) 
215        {
216                $_ = $contents[$pos++];
217                if (/^\s*<trkpt.*\slon=["']([0-9.eE-]+)["'] lat=["']([0-9.eE-]+)["']/)
218                {
219                        $polybuf .= sprintf "\t%f\t%f\n", $1,$2;
220                } 
221                elsif (/^\s*<trk>/) 
222                {
223                        $polybuf = "";
224                        $poly_id++;
225                }
226                elsif (/^\s*<\/trk>/) 
227                {
228                        $outbuf .= "$poly_id\n$polybuf"."END\n";
229                }
230        }
231
232        $poly_file = "polygon" unless defined($poly_file);
233        return "$poly_file\n$outbuf"."END\n";
234}
235
236sub wkt2poly {
237        error("wkt2poly not implemented yet");
238}
239
240sub osm2poly {
241        my @contents = split /^/, $_[0];
242        my $pos = 0;
243        my $poly_id;
244        my $poly_file;
245        my $polybuf;
246        my $outbuf;
247        my $nodes;
248        my $id=0;
249
250        while($pos <= $#contents) 
251        {
252                $_ = $contents[$pos++];
253                if (/^\s*<node.*\sid=["']([0-9-]+)['"].*lat=["']([0-9.eE-]+)["'] lon=["']([0-9.eE-]+)["']/)
254                {
255                        $nodes->{$1}=[$2,$3];
256                }
257                elsif (/^\s*<way /)
258                {
259                        undef $poly_id;
260                        undef $poly_file;
261                        $polybuf = "";
262                }
263                elsif (defined($polybuf) && /k=["'](.*)["']\s*v=["'](.*?)["']/)
264                {
265                        if ($1 eq "polygon_file") 
266                        {
267                                $poly_file=$2;
268                        }
269                        elsif ($1 eq "polygon_id")
270                        {
271                                $poly_id=$2;
272                        }
273                        elsif ($1 ne "note")
274                        {
275                                error("cannot process tag '$1'");
276                        }
277                }
278                elsif (/^\s*<nd ref=['"]([0-9-]+)["']/)
279                {
280                        my $id=$1;
281                        error("dangling reference to node $id") unless defined($nodes->{$id});
282                        $polybuf .= sprintf("   %f   %f\n", $nodes->{$id}->[1], $nodes->{$id}->[0]);
283                }
284                elsif (/^\s*<\/way/) 
285                {
286                        if (!defined($polybuf))
287                        {
288                                error("incomplete way definition");
289                        }
290                        $poly_id = ++$id unless defined($poly_id);
291                        $outbuf .= "$poly_id\n$polybuf"."END\n";
292                        undef $polybuf;
293                }
294        }
295        $poly_file = "polygon" unless defined($poly_file);
296        return "$poly_file\n$outbuf"."END\n";
297}
298
299sub openlayers {
300        error("no OpenLayers output yet");
301}
Note: See TracBrowser for help on using the repository browser.