[OSM-dev] tiles cut corners

Lars Aronsson lars at aronsson.se
Sat Feb 25 19:32:17 GMT 2006


I think that the map viewer fails to render line segments that cut 
across a corner of a tile, e.g. where node_a is to the west and 
node_b is to the north of the tile borders.  This becomes apparent 
at deep zoom levels or where line segments are very long.  One 
example where this happens in three places is 
http://www.openstreetmap.org/index.html?lat=58.379&lon=15.419&zoom=15

But it shows also in less extreme cases, where a few pixels can be 
missing from a road.  I think this is what happens at the very 
center of 
http://www.openstreetmap.org/index.html?lat=58.3799&lon=15.4240&zoom=12

This effect is demoralizing to the careful map editor.  The 
resulting map looks as if she missed something.  As if Wikipedia 
would introduce spelling errors in the text you wrote.

I think the street tiles are generated with 
svn/ruby/api/wms/streets.rbx and the function dao.getnodes() in
svn/ruby/api/osm/dao.rb where the SQL statement is:

  select id, latitude, longitude, visible, tags
  from (select *
        from (select nodes.id, nodes.latitude, nodes.longitude, 
              nodes.visible, nodes.tags
              from nodes, nodes as a 
              where a.latitude > #{lat2}  and a.latitude < #{lat1}
                and a.longitude > #{lon1} and a.longitude < #{lon2}
                and nodes.id = a.id
              order by nodes.timestamp desc) as b
        group by id) as c
  where visible = true
    and latitude > #{lat2}  and latitude < #{lat1}
    and longitude > #{lon1} and longitude < #{lon2}

This code is hard to read as it is, and it doesn't get better from 
the fact that lat2 < lat1 even though lon1 < lon2.  The call is 
dao.getnodes(trlat, bllon, bllat, trlon), whereas the argument 
order in the CGI interface is bbox=bllon,bllat,trlon,trlat.  I 
must admit I don't fully understand what this deeply nested SQL 
statement does.  For example, where do "b" and "c" go?  Does this 
statement select any node outside of the current tile?  Isn't it 
in fact equivalent to the following?

  select id, latitude, longitude
  from nodes
  where latitude > minlat
    and latitude < maxlat
    and longitude > minlon
    and longitude < maxlon
    and visible = true

In order to include line segments that cut corners, it is 
necessary to include lines that begin and end outside of the 
current tile.  The naive way I would have implemented this is to 
add a margin around the tile, equal to the maximum length of a 
line segment, and simply do

  select id, latitude, longitude
  from nodes
  where latitude > minlat - margin
    and latitude < maxlat + margin
    and longitude > minlon - margin
    and longitude < maxlon + margin
    and visible = true

On the other hand, it has the drawback that a margin would have to 
be specified and no segments longer than this should be allowed.  
Such a margin could perhaps be 0.005 degrees or 550 meters.


-- 
  Lars Aronsson (lars at aronsson.se)
  Aronsson Datateknik - http://aronsson.se




More information about the dev mailing list