Import
This commit is contained in:
commit
7020a51ecc
7 changed files with 746 additions and 0 deletions
15
src/basic-osm-converter/import.sh
Executable file
15
src/basic-osm-converter/import.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#! /bin/bash
|
||||
|
||||
rm -f $1
|
||||
cat osm.sql | grep -vi "CREATE INDEX" | sqlite3 $1
|
||||
cat spatial.sql | sqlite3 $1
|
||||
echo "Importing $2 into $1"
|
||||
./import_osm.pl $1 < $2
|
||||
echo "Creating indexes"
|
||||
cat osm.sql | grep -i "CREATE INDEX" | sqlite3 $1
|
||||
echo 'Analyzing'
|
||||
sqlite3 $1 'analyze'
|
||||
echo 'Creating spatial index'
|
||||
sqlite3 $1 'insert into way_index (id,minLat,maxLat,minLon,maxLon) select way_id,min(lat),max(lat),min(lon),max(lon) from way_node,node where way_node.node_id=node.id group by way_id'
|
||||
echo 'Creating way coords'
|
||||
sqlite3 $1 'insert into way_coord_text (id,lat,lon) select way_id,group_concat(lat),group_concat(lon) from (select way_id,lat,lon from way_node,node where node_id=id order by way_id,node_number) group by way_id'
|
164
src/basic-osm-converter/import_osm.pl
Executable file
164
src/basic-osm-converter/import_osm.pl
Executable file
|
@ -0,0 +1,164 @@
|
|||
#! /usr/bin/perl -w
|
||||
|
||||
use XML::Parser;
|
||||
use DBI;
|
||||
use strict;
|
||||
|
||||
my $dbname = shift;
|
||||
my $count = 0;
|
||||
|
||||
my $parser = new XML::Parser(ErrorContext => 2);
|
||||
|
||||
$parser->setHandlers(Char => \&char_handler,
|
||||
Start => \&start_handler,
|
||||
End => \&end_handler);
|
||||
# Default => \&default_handler);
|
||||
|
||||
my $file = shift;
|
||||
|
||||
my $dbargs = {AutoCommit => 0,
|
||||
PrintError => 1,
|
||||
};
|
||||
|
||||
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbname","","",$dbargs);
|
||||
$dbh->do("PRAGMA synchronous = OFF");
|
||||
if ($dbh->err()) { die "$DBI::errstr\n"; }
|
||||
|
||||
print "*\n";
|
||||
|
||||
if(defined $file and -f $file){
|
||||
$parser->parsefile($file);
|
||||
}
|
||||
else{
|
||||
$parser->parse(\*STDIN);
|
||||
}
|
||||
|
||||
$dbh->commit();
|
||||
$dbh->disconnect();
|
||||
|
||||
################
|
||||
## End of main
|
||||
################
|
||||
|
||||
my $id;
|
||||
my %tags;
|
||||
my %node_attrs;
|
||||
my $node_count = 0;
|
||||
my $node_id;
|
||||
my $relation_count = 0;
|
||||
my $sequence;
|
||||
my $node_count;
|
||||
my $way_count;
|
||||
my $relation_count;
|
||||
my $way_id;
|
||||
my $relation_id;
|
||||
my $node_number;
|
||||
|
||||
sub start_handler
|
||||
{
|
||||
my( $parseinst, $element, %attrs ) = @_;
|
||||
SWITCH: {
|
||||
if ($element eq "node") {
|
||||
$dbh->do("insert into node (id, lat, lon) values ($attrs{id},$attrs{lat},$attrs{lon})");
|
||||
if ($dbh->err()) { die "$DBI::errstr\n"; }
|
||||
$node_count += 1;
|
||||
if($node_count % 1000 == 0){
|
||||
print "nodes: ",$node_count,"\n";
|
||||
}
|
||||
$node_id = $attrs{id};
|
||||
if($node_count % 100000 == 0){
|
||||
$dbh->commit();
|
||||
if ($dbh->err()) { die "$DBI::errstr\n"; }
|
||||
# $dbh->begin();
|
||||
# if ($dbh->err()) { die "$DBI::errstr\n"; }
|
||||
}
|
||||
|
||||
last SWITCH;
|
||||
}
|
||||
if ($element eq "way") {
|
||||
$dbh->do("insert into way (id) values ($attrs{id})");
|
||||
if ($dbh->err()) { die "$DBI::errstr\n"; }
|
||||
$way_id = $attrs{id};
|
||||
$node_number = 0;
|
||||
$way_count += 1;
|
||||
if($way_count % 1000 == 0){
|
||||
print "ways: ",$way_count,"\n";
|
||||
}
|
||||
last SWITCH;
|
||||
}
|
||||
if ($element eq "relation") {
|
||||
$dbh->do("insert into relation (id) values ($attrs{id})");
|
||||
if ($dbh->err()) { die "$DBI::errstr\n"; }
|
||||
$relation_id = $attrs{id};
|
||||
$relation_count += 1;
|
||||
$sequence = 0;
|
||||
if($relation_count % 1000 == 0){
|
||||
print "relations: ",$relation_count,"\n";
|
||||
}
|
||||
last SWITCH;
|
||||
}
|
||||
if ($element eq "nd" and defined $way_id) {
|
||||
$dbh->do("insert into way_node (way_id,node_id,node_number) values ($way_id,$attrs{ref},$node_number)");
|
||||
if ($dbh->err()) { die "$DBI::errstr\n"; }
|
||||
$node_number += 1;
|
||||
last SWITCH;
|
||||
}
|
||||
if ($element eq "tag" ) {
|
||||
if(defined $way_id){
|
||||
my $q = "insert into way_tag (id,key,value) values ($way_id,".$dbh->quote($attrs{k}).",".$dbh->quote($attrs{v}).")";
|
||||
$dbh->do("$q");
|
||||
if ($dbh->err()) { print $q,"\n"; die "$DBI::errstr\n"; }
|
||||
}
|
||||
elsif(defined $node_id){
|
||||
my $q = "insert into node_tag (id,key,value) values ($node_id,".$dbh->quote($attrs{k}).",".$dbh->quote($attrs{v}).")";
|
||||
$dbh->do("$q");
|
||||
if ($dbh->err()) { print $q,"\n"; die "$DBI::errstr\n"; }
|
||||
}
|
||||
elsif(defined $relation_id){
|
||||
my $q = "insert into relation_tag (id,key,value) values ($relation_id,".$dbh->quote($attrs{k}).",".$dbh->quote($attrs{v}).")";
|
||||
$dbh->do("$q");
|
||||
if ($dbh->err()) { print $q,"\n"; die "$DBI::errstr\n"; }
|
||||
}
|
||||
last SWITCH;
|
||||
}
|
||||
if ($element eq "member" ) {
|
||||
my $q;
|
||||
if($attrs{type} eq 'node'){
|
||||
$q = "insert into relation_member_node (id,node_id,role,sequence_number) values ($relation_id,".$dbh->quote($attrs{ref}).",".$dbh->quote($attrs{role}).",$sequence)";
|
||||
}
|
||||
if($attrs{type} eq 'way'){
|
||||
$q = "insert into relation_member_way (id,way_id,role,sequence_number) values ($relation_id,".$dbh->quote($attrs{ref}).",".$dbh->quote($attrs{role}).",$sequence)";
|
||||
}
|
||||
if($attrs{type} eq 'relation'){
|
||||
$q = "insert into relation_member_relation (id,relation_id,role,sequence_number) values ($relation_id,".$dbh->quote($attrs{ref}).",".$dbh->quote($attrs{role}).",$sequence)";
|
||||
}
|
||||
$sequence += 1;
|
||||
if(defined $q){
|
||||
$dbh->do("$q");
|
||||
if ($dbh->err()) { print $q,"\n"; die "$DBI::errstr\n"; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub end_handler
|
||||
{
|
||||
my( $parseinst, $element ) = @_;
|
||||
if($element eq 'way'){
|
||||
undef $way_id;
|
||||
}elsif($element eq 'node'){
|
||||
undef $node_id;
|
||||
}elsif($element eq 'relation'){
|
||||
undef $relation_id;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub char_handler
|
||||
{
|
||||
# This is just here to reduce the noise seen by
|
||||
# the default handler
|
||||
return;
|
||||
} # End of char_handler
|
149
src/basic-osm-converter/maketiles.pl
Executable file
149
src/basic-osm-converter/maketiles.pl
Executable file
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/perl -w
|
||||
use DBI;
|
||||
use Time::HiRes qw(gettimeofday tv_interval);
|
||||
use strict;
|
||||
use File::Spec;
|
||||
use navigator_lib;
|
||||
|
||||
my $dbname = $ARGV[0] or die "Usage: ./maketiles.pl database.db";
|
||||
my $dbargs = {AutoCommit => 0,
|
||||
PrintError => 1,
|
||||
};
|
||||
|
||||
|
||||
my $latmin;
|
||||
my $latmax;
|
||||
my $lonmin;
|
||||
my $lonmax;
|
||||
|
||||
my $latcenter = 55.75;
|
||||
my $loncenter = 37.62;
|
||||
#lat=55.7543&lon=37.6211
|
||||
#my ( $width, $height ) = ( 240, 320 );
|
||||
#my ( $width, $height ) = ( 640,480 );
|
||||
#my $zoom = $width/0.02;
|
||||
|
||||
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbname","","",$dbargs);
|
||||
#$dbh->do("PRAGMA synchronous = OFF");
|
||||
if ($dbh->err()) { die "$DBI::errstr\n"; }
|
||||
|
||||
my $i;
|
||||
my $j;
|
||||
my $n = 50;
|
||||
my $tile_step = 0.01;
|
||||
for($i=-$n;$i<=$n;$i+=1){
|
||||
for($j=-$n;$j<=$n;$j+=1){
|
||||
$latmin = $latcenter + $i*$tile_step;
|
||||
$latmax = $latmin + $tile_step;
|
||||
$lonmin = $loncenter + $j*$tile_step;
|
||||
$lonmax = $lonmin + $tile_step;
|
||||
my $filename = latlon_to_filename($latmin, $lonmin);
|
||||
my ($vol, $dir, $fname) = File::Spec->splitpath($filename);
|
||||
# print $vol,$dir," xxx\n";
|
||||
my $p = '.';
|
||||
foreach my $cd (File::Spec->splitdir($dir)){
|
||||
$p = File::Spec->catdir($p, $cd);
|
||||
mkdir $p;
|
||||
}
|
||||
open my $file, '>', $filename or die "create map file: $!";
|
||||
my $q = 'select way_coord_text.id,lat,lon,key,value from way_index,way_tag,way_coord_text where maxLat >= '.$latmin.' and minLat <= '.$latmax.' and maxLon >= '.$lonmin.' and minLon <= '.$lonmax.' and way_index.id=way_coord_text.id and way_coord_text.id = way_tag.id and (key like \'highway\' or key = \'natural\' or key = \'landuse\'or key=\'building\' or key=\'waterway\' or key=\'leisure\' )';
|
||||
print $q,"\n";
|
||||
my $t0 = [gettimeofday];
|
||||
my $res = $dbh->selectall_arrayref($q);
|
||||
my $el1 = tv_interval ( $t0, [gettimeofday]);
|
||||
if ($dbh->err()) { die "$DBI::errstr\n"; }
|
||||
my $r;
|
||||
my $way_count=0;
|
||||
my $node_count=0;
|
||||
foreach $r (@$res){
|
||||
my @wlat = split(',', $r->[1]);
|
||||
my @wlon = split(',', $r->[2]);
|
||||
my @coord;
|
||||
$way_count += 1;
|
||||
while(@wlat){
|
||||
my ($sx, $sy) = ((shift @wlat), (shift @wlon));
|
||||
push @coord, $sx, $sy;
|
||||
$node_count += 1;
|
||||
}
|
||||
my $k = $r->[3];
|
||||
my $v = $r->[4];
|
||||
if($k eq 'highway' and ($v eq 'primary' or $v eq 'motorway' or $v eq 'trunk')){
|
||||
line1($file, $r->[0], 1, @coord);
|
||||
}
|
||||
elsif($k eq 'highway' and ($v eq 'motorway_link' or $v eq 'trunk_link' or $v eq 'primary_link')){
|
||||
line1($file, $r->[0], 2, @coord);
|
||||
}
|
||||
elsif($k eq 'highway' and $v eq 'secondary'){
|
||||
line1($file, $r->[0], 3, @coord);
|
||||
}
|
||||
elsif($k eq 'highway' and ($v eq 'tertiary' or $v eq 'residential' or $v eq 'living_street')){
|
||||
line1($file, $r->[0], 4, @coord);
|
||||
}
|
||||
elsif($k eq 'highway' and ($v eq 'service' or $v eq 'unclassified')){
|
||||
line1($file, $r->[0], 5, @coord);
|
||||
}
|
||||
elsif($k eq 'building' and $v eq 'yes'){
|
||||
poly($file, $r->[0], 6, @coord);
|
||||
}
|
||||
elsif($k eq 'highway' and $v eq 'footway' or $v eq 'path' or $v eq 'track'){
|
||||
}
|
||||
elsif(($k eq 'natural' and $v eq 'wood') or ($k eq 'landuse' and $v eq 'forest') or ($k eq 'leisure' and $v eq 'park')){
|
||||
poly($file, $r->[0], 7, @coord);
|
||||
}
|
||||
elsif($k eq 'highway'){
|
||||
line1($file, $r->[0], 8, @coord);
|
||||
}
|
||||
elsif($k eq 'landuse' and $v eq 'industrial'){
|
||||
poly($file, $r->[0], 9, @coord);
|
||||
}
|
||||
elsif(($k eq 'natural' and $v eq 'water') or ($k eq 'waterway' and $v eq 'riverbank')){
|
||||
poly($file, $r->[0], 10, @coord);
|
||||
}
|
||||
elsif($k eq 'landuse' and $v eq 'residential'){
|
||||
poly($file, $r->[0], 11, @coord);
|
||||
}
|
||||
elsif(($k eq 'waterway' and $v eq 'river')){
|
||||
line1($file, $r->[0], 12, @coord);
|
||||
}
|
||||
elsif(($k eq 'waterway' and $v eq 'stream')){
|
||||
line1($file, $r->[0], 13, @coord);
|
||||
}
|
||||
elsif(($k eq 'landuse' and $v eq 'allotments')){
|
||||
poly($file, $r->[0], 14, @coord);
|
||||
}
|
||||
elsif(($k eq 'landuse')){
|
||||
poly($file, $r->[0], 15, @coord);
|
||||
}
|
||||
}
|
||||
my $el2 = tv_interval ( $t0, [gettimeofday]);
|
||||
print "Ways: $way_count nodes: $node_count\n";
|
||||
print "SQL: $el1 draw: ",$el2-$el1,"\n";
|
||||
close $file;
|
||||
}
|
||||
}
|
||||
|
||||
sub line1{
|
||||
my $a;
|
||||
my $f = shift;
|
||||
my $id = shift;
|
||||
my $t = shift;
|
||||
print $f "L $id $t";
|
||||
foreach $a (@_){
|
||||
print $f " $a";
|
||||
}
|
||||
print $f "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub poly{
|
||||
my $a;
|
||||
my $f = shift;
|
||||
my $id = shift;
|
||||
my $t = shift;
|
||||
print $f "P $id $t";
|
||||
foreach $a (@_){
|
||||
print $f " $a";
|
||||
}
|
||||
print $f "\n";
|
||||
return 0;
|
||||
}
|
14
src/basic-osm-converter/navigator_lib.pm
Normal file
14
src/basic-osm-converter/navigator_lib.pm
Normal file
|
@ -0,0 +1,14 @@
|
|||
package navigator_lib;
|
||||
use Exporter;
|
||||
use base Exporter;
|
||||
|
||||
@EXPORT = qw(latlon_to_filename);
|
||||
|
||||
sub latlon_to_filename{
|
||||
my ($i, $j) = @_;
|
||||
$i = int($i*100+0.5);
|
||||
$j = int($j*100+0.5);
|
||||
return "data/".int($i/100).'/'.int($j/100).'/'.($i%100).'/'.($j%100).'.map';
|
||||
}
|
||||
|
||||
1;
|
111
src/basic-osm-converter/osm.sql
Normal file
111
src/basic-osm-converter/osm.sql
Normal file
|
@ -0,0 +1,111 @@
|
|||
create table node (
|
||||
id INTEGER PRIMARY KEY,
|
||||
lat FLOAT,
|
||||
lon FLOAT
|
||||
);
|
||||
|
||||
create table way(
|
||||
id INTEGER PRIMARY KEY
|
||||
);
|
||||
|
||||
create table way_node (
|
||||
node_number INTEGER,
|
||||
way_id INTEGER,
|
||||
node_id INTEGER,
|
||||
FOREIGN KEY(way_id) REFERENCES way(id),
|
||||
FOREIGN KEY(node_id) REFERENCES node(id)
|
||||
);
|
||||
|
||||
CREATE INDEX way_node_way_id_idx on way_node (way_id);
|
||||
CREATE INDEX way_node_node_id_idx on way_node (node_id);
|
||||
|
||||
create table way_tag(
|
||||
id INTEGER,
|
||||
key VARCHAR(20),
|
||||
value VARCHAR(20),
|
||||
FOREIGN KEY(id) REFERENCES way(id)
|
||||
);
|
||||
|
||||
CREATE INDEX way_tag_id_idx on way_tag (id);
|
||||
CREATE INDEX way_tag_key_idx on way_tag (key);
|
||||
CREATE INDEX way_tag_value_idx on way_tag (value);
|
||||
CREATE INDEX way_tag_key_value_idx on way_tag (key,value);
|
||||
|
||||
create table node_tag(
|
||||
id INTEGER,
|
||||
key VARCHAR(20),
|
||||
value VARCHAR(20),
|
||||
FOREIGN KEY(id) REFERENCES node(id)
|
||||
);
|
||||
|
||||
CREATE INDEX node_tag_id_idx on node_tag (id);
|
||||
CREATE INDEX node_tag_key_idx on node_tag (key);
|
||||
CREATE INDEX node_tag_value_idx on node_tag (value);
|
||||
CREATE INDEX node_tag_key_value_idx on node_tag (key,value);
|
||||
|
||||
create table relation(
|
||||
id INTEGER PRIMARY KEY
|
||||
);
|
||||
|
||||
create table relation_tag(
|
||||
id INTEGER,
|
||||
key VARCHAR(20),
|
||||
value VARCHAR(20),
|
||||
FOREIGN KEY(id) REFERENCES relation(id)
|
||||
);
|
||||
|
||||
CREATE INDEX relation_tag_id_idx on relation_tag (id);
|
||||
CREATE INDEX relation_tag_key_idx on relation_tag (key);
|
||||
CREATE INDEX relation_tag_value_idx on relation_tag (value);
|
||||
CREATE INDEX relation_tag_key_value_idx on relation_tag (key,value);
|
||||
|
||||
create table relation_member_node(
|
||||
id INTEGER,
|
||||
node_id INTEGER,
|
||||
sequence_number INTEGER NOT NULL,
|
||||
role VARCHAR(20) NOT NULL,
|
||||
FOREIGN KEY(id) REFERENCES relation(id)
|
||||
FOREIGN KEY(node_id) REFERENCES node(id)
|
||||
);
|
||||
|
||||
CREATE INDEX relation_member_node_id_idx on relation_member_node (id);
|
||||
CREATE INDEX relation_member_node_node_id_idx on relation_member_node (node_id);
|
||||
CREATE INDEX relation_member_node_role_idx on relation_member_node (role);
|
||||
|
||||
create table relation_member_way(
|
||||
id INTEGER,
|
||||
way_id INTEGER,
|
||||
sequence_number INTEGER NOT NULL,
|
||||
role VARCHAR(20) NOT NULL,
|
||||
FOREIGN KEY(id) REFERENCES relation(id)
|
||||
FOREIGN KEY(way_id) REFERENCES way(id)
|
||||
);
|
||||
|
||||
CREATE INDEX relation_member_way_id_idx on relation_member_way (id);
|
||||
CREATE INDEX relation_member_way_way_id_idx on relation_member_way (way_id);
|
||||
CREATE INDEX relation_member_way_role_idx on relation_member_way (role);
|
||||
|
||||
create table relation_member_relation(
|
||||
id INTEGER,
|
||||
relation_id INTEGER,
|
||||
sequence_number INTEGER NOT NULL,
|
||||
role VARCHAR(20) NOT NULL,
|
||||
FOREIGN KEY(id) REFERENCES relation(id)
|
||||
FOREIGN KEY(relation_id) REFERENCES relation(id)
|
||||
);
|
||||
|
||||
CREATE INDEX relation_member_relation_id_idx on relation_member_relation (id);
|
||||
CREATE INDEX relation_member_relation_relation_id_idx on relation_member_relation (relation_id);
|
||||
CREATE INDEX relation_member_relation_role_idx on relation_member_relation (role);
|
||||
|
||||
-- CREATE VIEW pt_route AS SELECT id,value AS type FROM relation_tag WHERE key = 'route' AND value IN ('bus', 'trolleybus', 'tram');
|
||||
create view pt_route as select id,value as type from relation_tag where key = 'route' and value in ('bus', 'trolleybus', 'tram') and id in (select id from relation_tag where key = 'type' and value = 'route');
|
||||
-- create view pt_route_ref as select pt_route.id as id, pt_route.type as type,value as ref from pt_route,relation_tag where pt_route.id = relation_tag.id and key='ref';
|
||||
create view pt_route_ref as select pt_route.id as id, pt_route.type as type,value as ref from pt_route,relation_tag where relation_tag.id in (select id from pt_route) and pt_route.id = relation_tag.id and key='ref';
|
||||
-- create view pt_way as select distinct way_id as id,type,ref from relation_member_way,pt_route_ref where relation_member_way.id = pt_route_ref.id;
|
||||
create view pt_way_ref as select distinct way_id as id,type,ref from pt_route_ref,relation_member_way where relation_member_way.id = pt_route_ref.id;
|
||||
create view pt_way_id as select distinct way_id as id from pt_route_ref,relation_member_way where relation_member_way.id = pt_route_ref.id;
|
||||
--create view pt_way_node as select way_id,node_id from way_node where way_id in (select id from pt_way_id);
|
||||
create view pt_way_node as select way_id,node_id,node_number from way_node where way_id in (select id from pt_way_id);
|
||||
create view pt_stop as select distinct id,node_id from relation_member_node where id in (select id from pt_route) and role in ('forward:stop','backward:stop','stop');
|
||||
create view pt_stop_ref as select distinct node_id as id,type,ref from pt_route_ref,relation_member_node where relation_member_node.id = pt_route_ref.id;
|
16
src/basic-osm-converter/spatial.sql
Normal file
16
src/basic-osm-converter/spatial.sql
Normal file
|
@ -0,0 +1,16 @@
|
|||
CREATE VIRTUAL TABLE way_index USING rtree(
|
||||
id, -- Integer primary key
|
||||
minLat, maxLat, -- Minimum and maximum X coordinate
|
||||
minLon, maxLon -- Minimum and maximum Y coordinate
|
||||
);
|
||||
|
||||
CREATE TABLE way_coord(
|
||||
id INTEGER PRIMARY KEY,
|
||||
coord BLOB
|
||||
);
|
||||
|
||||
CREATE TABLE way_coord_text(
|
||||
id INTEGER PRIMARY KEY,
|
||||
lat TEXT,
|
||||
lon TEXT
|
||||
);
|
277
src/kothic.py
Executable file
277
src/kothic.py
Executable file
|
@ -0,0 +1,277 @@
|
|||
#!/usr/bin/env python
|
||||
#use Cairo;
|
||||
#import cairo
|
||||
#use Gtk2 '-init';
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
import cairo
|
||||
import math
|
||||
import string
|
||||
import threading
|
||||
import time
|
||||
import Queue
|
||||
|
||||
#use Glib qw(TRUE FALSE);
|
||||
#use Time::HiRes qw(gettimeofday tv_interval);
|
||||
#use strict;
|
||||
#use POSIX qw(ceil floor);
|
||||
#use style qw(@style);
|
||||
#use navigator_lib;
|
||||
|
||||
#my $dbname = "moscow.db";
|
||||
#my $dbargs = {AutoCommit => 0,
|
||||
# PrintError => 1,
|
||||
#};
|
||||
#
|
||||
|
||||
#my $latmin;
|
||||
#my $latmax;
|
||||
#my $lonmin;
|
||||
#my $lonmax;
|
||||
|
||||
#my $latcenter = 55.6304;
|
||||
#my $loncenter = 37.49305;
|
||||
|
||||
class Renderer(threading.Thread):
|
||||
def __init__(self, comm):
|
||||
self.comm = comm
|
||||
threading.Thread.__init__(self)
|
||||
def run(self):
|
||||
print ("Thread started")
|
||||
self.tc = {}
|
||||
while(True):
|
||||
while(True):
|
||||
request = self.comm[0].get()
|
||||
if(self.comm[0].empty):
|
||||
break
|
||||
print (" got request:", request)
|
||||
res = RasterTile(request[2][0], request[2][1])
|
||||
res.update_surface(request[0][0], request[0][1], request[1], self.tc, request[3])
|
||||
print (" render complete")
|
||||
comm[1].put(res)
|
||||
|
||||
class Navigator:
|
||||
def __init__(self, comm):
|
||||
self.comm = comm
|
||||
self.lat_c = 55.6304
|
||||
self.lon_c = 37.49305
|
||||
self.width, self.height = 640, 480
|
||||
self.zoom = self.width/0.02;
|
||||
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
self.dx = 0
|
||||
self.dy = 0
|
||||
self.drag = False
|
||||
self.tilecache = {}
|
||||
self.border = 200
|
||||
self.rastertile = None
|
||||
self.f = True
|
||||
undef = None
|
||||
self.style = [
|
||||
[None, None, None, 0],
|
||||
[undef, [6.0, [0,0,0]], [4.0, [1, 1, .7]], 1],
|
||||
[undef, [4.5, [0,0,0]], [2.5, [1, 1, .7]], 2],
|
||||
[undef, [3.5, [0,0,0]], [2.5, [1, 1, .7]], 3],
|
||||
[undef, [2.8, [0,0,0]], [2.0, [1, 1, 1]], 4],
|
||||
[undef, undef, [1.0, [1, 1, 1]], 5],
|
||||
[undef, [0, [0.7, 0.4, 0.4]], undef, 6],
|
||||
[[1, [0.30, 0.5, 0.30]], undef, undef, 7],
|
||||
[undef, undef, [2, [1, 0.3, 0.3]], 8],
|
||||
[[0, [0.7, 0.6, 0.6]], undef, undef, 9],
|
||||
[[0, [0.4, 0.4, 1.0]], undef, undef, 10],
|
||||
[[0, [0.6, 0.6, 0.6]], undef, undef, 11],
|
||||
[undef, [3.5, [0.4, 0.4, 1.0]], undef, 12],
|
||||
[undef, [2, [0.4, 0.4, 1.0]], undef, 13],
|
||||
[[0, [0.72, 0.51, 0.32]], undef, undef, 14],
|
||||
[[0, [1, 0.0, 0.0]], undef, undef, 0] #unknown landuse
|
||||
]
|
||||
da = gtk.DrawingArea()
|
||||
da.add_events(gtk.gdk.BUTTON1_MOTION_MASK)
|
||||
da.add_events(gtk.gdk.POINTER_MOTION_MASK)
|
||||
da.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
||||
da.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
|
||||
# self.window.add_events(gtk.gdk.BUTTON1_MOTION_MASK)
|
||||
da.connect("expose_event",self.expose_ev)
|
||||
da.connect("motion_notify_event",self.motion_ev)
|
||||
da.connect("button_press_event",self.press_ev)
|
||||
da.connect("button_release_event",self.release_ev)
|
||||
self.da = da
|
||||
# self.surface = cairo.ImageSurfaceicreate(gtk.RGB24, self.width, self.height)
|
||||
self.window.set_size_request(self.width, self.height)
|
||||
self.window.add(da)
|
||||
self.window.connect("delete_event", self.delete_ev)
|
||||
def motion_ev(self, widget, event):
|
||||
# print("Motion")
|
||||
if self.drag:
|
||||
self.dx = event.x - self.drag_x
|
||||
self.dy = event.y - self.drag_y
|
||||
if((abs(self.dx) > 100 or abs(self.dy) > 100) and self.f):
|
||||
self.comm[0].put((self.rastertile.screen2latlon(self.rastertile.w/2 - self.dx, self.rastertile.h/2 - self.dy), self.zoom, (self.width + self.border*2, self.height + self.border*2), self.style))
|
||||
self.request_d = (self.dx, self.dy)
|
||||
self.f = False
|
||||
if not self.comm[1].empty():
|
||||
self.rastertile = self.comm[1].get()
|
||||
self.f = True
|
||||
self.drag_x += self.request_d[0]
|
||||
self.drag_y += self.request_d[1]
|
||||
self.dx = event.x - self.drag_x
|
||||
self.dy = event.y - self.drag_y
|
||||
widget.queue_draw()
|
||||
def delete_ev(self, widget, event):
|
||||
gtk.main_quit()
|
||||
def press_ev(self, widget, event):
|
||||
print("Start drag")
|
||||
self.drag = True
|
||||
self.drag_x = event.x
|
||||
self.drag_y = event.y
|
||||
def release_ev(self, widget, event):
|
||||
print("Stop drag")
|
||||
self.drag = False
|
||||
# print("ll:", self.latcenter, self.loncenter)
|
||||
print("LL before: ",self.lat_c, self.lon_c)
|
||||
print("dd: ",self.dx, self.dy)
|
||||
self.lat_c, self.lon_c = self.rastertile.screen2latlon(self.rastertile.w/2 - self.dx, self.rastertile.h/2 - self.dy);
|
||||
self.dx = self.dy = 0
|
||||
self.f = True
|
||||
print("LL after: ",self.lat_c, self.lon_c)
|
||||
# self.rastertile.update_surface( self.lat_c, self.lon_c, self.zoom, self.tilecache, self.style)
|
||||
self.comm[0].put(((self.lat_c, self.lon_c), self.zoom, (self.width + self.border*2, self.height + self.border*2), self.style))
|
||||
widget.queue_draw()
|
||||
def expose_ev(self, widget, event):
|
||||
# print("Expose")
|
||||
if(widget.allocation.width != self.width):
|
||||
print("Rrresize!")
|
||||
self.width = widget.allocation.width
|
||||
self.height = widget.allocation.height
|
||||
self.rastertile = None
|
||||
if self.rastertile is None:
|
||||
self.rastertile = RasterTile(self.width + self.border*2, self.height + self.border*2)
|
||||
self.rastertile.update_surface(self.lat_c, self.lon_c, self.zoom, self.tilecache, self.style)
|
||||
cr = widget.window.cairo_create()
|
||||
cr.set_source_surface(self.rastertile.surface, self.dx-self.border, self.dy - self.border)
|
||||
cr.paint()
|
||||
# cr.
|
||||
|
||||
def main(self):
|
||||
self.window.show_all()
|
||||
gtk.main()
|
||||
|
||||
def line(cr, c):
|
||||
cr.move_to(c[0], c[1])
|
||||
for k in range(2, len(c), 2):
|
||||
cr.line_to(c[k], c[k + 1])
|
||||
cr.stroke()
|
||||
|
||||
def poly(cr, c):
|
||||
cr.move_to(c[0], c[1])
|
||||
for k in range(2, len(c), 2):
|
||||
cr.line_to(c[k], c[k + 1])
|
||||
cr.fill()
|
||||
|
||||
def ways(t):
|
||||
# return [y for x in t.itervalues() for y in x.itervalues()]
|
||||
r = {}
|
||||
for i in t.values():
|
||||
r.update(i)
|
||||
return r.values()
|
||||
|
||||
def load_tile(k):
|
||||
print("loading tile: ", k)
|
||||
f = open(key_to_filename(k))
|
||||
t = {}
|
||||
while True:
|
||||
str = f.readline()
|
||||
if str is None or str == "":
|
||||
break
|
||||
str = str.rstrip("\n")
|
||||
a = str.split(" ")
|
||||
w = Way(a[0], int(a[1]), int(a[2]), map(lambda x: float(x), a[3:]))
|
||||
t[w.id] = w
|
||||
f.close()
|
||||
return t
|
||||
|
||||
class RasterTile:
|
||||
def __init__(self, width, height):
|
||||
self.w = width
|
||||
self.h = height
|
||||
self.surface = cairo.ImageSurface(cairo.FORMAT_RGB24, self.w, self.h)
|
||||
self.x_offset = 0
|
||||
self.y_offset = 0
|
||||
self.lat_c = None
|
||||
self.lon_c = None
|
||||
self.zoom = None
|
||||
def screen2latlon(self, x, y):
|
||||
return -(y - self.h/2)/self.zoom + self.lat_c, (x - self.w/2)/(math.cos(self.lat_c*math.pi/180)*self.zoom) + self.lon_c
|
||||
def latlon2screen(self, lat, lon, lcc):
|
||||
return (lon - self.lon_c)*lcc*self.zoom + self.w/2, -(lat - self.lat_c)*self.zoom + self.h/2
|
||||
def update_surface(self, lat, lon, zoom, tilecache, style):
|
||||
self.zoom = zoom
|
||||
self.lat_c = lat
|
||||
self.lon_c = lon
|
||||
cr = cairo.Context(self.surface)
|
||||
cr.rectangle(0, 0, self.w, self.h)
|
||||
cr.set_source_rgb(0.7, 0.7, 0.7)
|
||||
cr.fill()
|
||||
latmin, lonmin = self.screen2latlon(0, self.h)
|
||||
latmax, lonmax = self.screen2latlon(self.w, 0)
|
||||
latkey_min = int(latmin*100)
|
||||
latkey_max = int(latmax*100)
|
||||
lonkey_min = int(lonmin*100)
|
||||
lonkey_max = int(lonmax*100)
|
||||
print(latmin, lonmin, latmax, lonmax)
|
||||
print( latkey_min, latkey_max, lonkey_min, lonkey_max)
|
||||
#FIXME: add time
|
||||
active_tile = set([(i,j) for i in range(latkey_min, latkey_max+1) for j in range(lonkey_min, lonkey_max+1)])
|
||||
print(active_tile)
|
||||
for k in tilecache.keys():
|
||||
if k not in active_tile:
|
||||
del tilecache[k]
|
||||
print("del tile:", k)
|
||||
for k in active_tile:
|
||||
if k not in tilecache:
|
||||
tilecache[k] = load_tile(k)
|
||||
#FIXME add time2
|
||||
ww = ways(tilecache)
|
||||
print("ways: ", len(ww))
|
||||
|
||||
ww.sort(key=lambda x: style[x.style][3])
|
||||
lcc = math.cos(self.lat_c*math.pi/180)
|
||||
for w in ww:
|
||||
cs = []
|
||||
for k in range(0, len(w.coords), 2):
|
||||
x, y = self.latlon2screen(w.coords[k], w.coords[k+1], lcc);
|
||||
cs.append(x)
|
||||
cs.append(y)
|
||||
w.cs = cs
|
||||
for passn in range(1, 4):
|
||||
print("pass ",passn)
|
||||
for w in ww:
|
||||
stn = w.style
|
||||
if stn < len(style) and style[stn] is not None and style[stn][passn-1] is not None:
|
||||
st = style[w.style][passn-1]
|
||||
cr.set_line_width(st[0])
|
||||
cr.set_source_rgb(st[1][0], st[1][1], st[1][2])
|
||||
if w.type == "L":
|
||||
line(cr, w.cs)
|
||||
elif w.type == "P":
|
||||
poly(cr, w.cs)
|
||||
|
||||
class Way:
|
||||
def __init__(self, type, id, style, coords):
|
||||
self.type = type
|
||||
self.id = id
|
||||
self.coords = coords
|
||||
self.style = style
|
||||
self.cs = None
|
||||
|
||||
def key_to_filename(k):
|
||||
return "data/" + str(k[0]//100) + "/" + str(k[1]//100) + "/" + str(k[0]%100) + "/" + str(k[1]%100) + ".map"
|
||||
|
||||
if __name__ == "__main__":
|
||||
comm = (Queue.Queue(), Queue.Queue())
|
||||
gtk.gdk.threads_init()
|
||||
nav = Navigator(comm)
|
||||
r = Renderer(comm)
|
||||
r.daemon = True
|
||||
r.start()
|
||||
nav.main()
|
Loading…
Add table
Reference in a new issue