[NUUG kart] Forenkle kystlinjer o.a. med JOSM "Delete unnecessary nodes"

Steinar Hamre steinarh at pvv.ntnu.no
Mon Jul 7 20:07:59 CEST 2008


On Mon, Jul 07, 2008 at 05:29:38PM +0200, Helge Hafting wrote:
> Kystlinjer inneholder ofte massevis av korte linjestykker som kommer 
> rett etter hverandre. Disse kan erstattes av en enkelt rett linje,
> noe som sparer massevis av punkter. Kartet er like bra, men
> mindre data å prosessere.

Dette er en av flere sideeffekter av den ikke-helt-optimale måten
disse kystlinjene har blitt laget og konvertert på.

> JOSM har en knapp "delete unnecessary nodes" som gjør akkurat dette.

Hmm... Hvor, og hvilken versjon? Hvilke begrensninger har den?

> Er det noen grunn til å ikke bruke denne funksjonen?


Jeg startet for en stund tilbake med noe kode for å gjøre noe med dette.
(tanken var å kjøre det før import av kystlinjene i Nordland,
men så kom noen meg i forkjøpet...)

Parametrene (derror < 0.017 and lerror < 0.000009)
er tillat feilmargin i vinkel (radianer) og avstand (grader)...
0.017 tilsvarer en grad sving og 0.000009 tilsvarer en meter.

Hvis det er interesse, så er det en lett sak  å få den til å generere
differ til OSM... (enklere enn å laste inn hele Norge i JOSM)


import math
from cElementTree import ElementTree

et = ElementTree()

tree = et.parse("test.osm")

allnodes = {}
delete = []

for node in tree.getiterator('node'):
    allnodes[node.get('id')] = (float(node.get('lat')), float(node.get('lon')))

for way in tree.getiterator('way'):
    tags={}
    for tag in way.getiterator("tag"):
        tags[tag.get('k')] = tag.get('v')
    if tags.get('created_by') != 'almien_coastlines': break
    if tags.get('natural') != 'coastline': break
    source = tags.get('source')
    if not source or len(source) < 3 or source[:3] != 'PGS': break
    waynodes=[ (nd.get('ref'),) + allnodes[nd.get('ref')]
               for nd in way.getiterator("nd") ]
    sid, slat, slon = waynodes[0]
    mid, mlat, mlon = waynodes[1]
    print way.get('id')
    for id,lat,lon in waynodes[2:]:
        mdir = math.atan2(mlat-slat, mlon-slon)
        dir = math.atan2(lat-slat, lon-slon)
        length = math.hypot(slat-lat, slon-lon)
        derror = abs(dir-mdir)
        lerror = length * abs(dir-mdir)
        print mid, derror*180/math.pi, lerror*1e7/90, length*1e7/90
        # error less than 1 meter and 1 degree in heading
        if (derror < 0.017 and lerror < 0.000009):
            delete.append(mid)
            print "delete"
            mid = id
        else:
            sid, slat, slon = mid, mlat, mlon
            mid, mlat, mlon = id, lat, lon
            
print len(allnodes),len(delete)


More information about the kart mailing list