User:Opk

From OpenStreetMap Wiki
Jump to navigation Jump to search
Babel user information
en-N This user has a native understanding of English.
de-3 Dieser Benutzer beherrscht Deutsch auf hohem Niveau.
Users by language

I support the license
upgrade to ODbL v 1.0

ODbL-Supporter.png


Drawing Buildings with Turtle Graphics

I find that mapping buildings using JOSM can be a bit fiddly and time consuming. Just getting it aligned to the roads correctly can be tricky - you can move an object East/West or North/South with the cursors but to move it parallel to a road isn't possible.

So I've written the following library in LOGO that replaces the LOGO turtle graphics primitives to draw nodes and ways for OpenStreetMap. The result is saved as a .osm file that can be loaded into JOSM.

; redefined logo turtle graphics primitives to create a .osm file

make "redefp "true

make "mt.draw "true
make "mt.start "true
make "mt.xpos 0
make "mt.ypos 0
make "mt.dir 0
make "mt.nodes []
make "mt.ways []
make "mt.origin [0 0]
make "mt.circum 40041455
make "mt.latmetre 360.0/mt.circum

to setorigin :pos
 make "mt.origin :pos
end

to abs :value
  ifelse less? :value 0 [ output minus :value ] [output :value]
end

; movement commands
to mt.find :xcor :ycor :list
  (local "cur "tail)
  if emptyp :list [output 0]
  make "cur first :list
  ifelse and (less? abs difference first cur xcor 0.001)(less? abs difference last cur ycor 0.001) [
    output 1
  ] [
    make "tail mt.find :xcor :ycor butfirst :list
    if not equalp :tail 0 [ make "tail sum :tail 1 ]
    output :tail
  ]
end

to mt.setxy :xcor :ycor
  local "node
  if and :mt.draw :mt.start [
    make "node mt.find :mt.xpos :mt.ypos :mt.nodes
    if equalp node 0 [
      make "mt.nodes lput (list :mt.xpos :mt.ypos) :mt.nodes
      make "node count :mt.nodes
    ]
    make "mt.ways lput (list node) mt.ways
  ]

  make "mt.xpos :xcor
  make "mt.ypos :ycor

  if :mt.draw [
    make "node mt.find :xcor :ycor :mt.nodes
    if equalp node 0 [
      make "mt.nodes lput (list :xcor :ycor) :mt.nodes
      make "node count :mt.nodes
    ]
    make "mt.ways lput lput node last mt.ways butlast mt.ways
    make "mt.start "false
  ]
end
copydef "setxy "mt.setxy

to mt.forward :dist
  (setxy sum mt.xpos product dist sin mt.dir
      sum mt.ypos product dist cos mt.dir)
end
copydef "forward "mt.forward

to mt.back :dist
  forward minus :dist
end
copydef "back "mt.back

to mt.setpos :pos
  setxy first :pos last :pos
end
copydef "setpos "mt.setpos

to mt.setx :xcor
  setxy :xcor :mt.ypos
end
copydef "setx "mt.setx

to mt.sety :ycor
  setxy :mt.xpos :ycor
end
copydef "setx "mt.setx

; functions to change the heading direction
to mt.right :degrees
  make "mt.dir modulo :mt.dir+:degrees 360
end
copydef "right "mt.right
copydef "rt "mt.right

to mt.left :degrees
  right minus :degrees
end
copydef "left "mt.left
copydef "lt "mt.left

to mt.setheading :degrees
  make "mt.dir modulo :degrees 360
end
copydef "setheading "mt.setheading

to mt.home
  setpos [0 0]
  setheading 0
end
copydef "home "mt.home

to mt.pos
  output list :mt.xpos :mt.ypos
end
copydef "pos "mt.pos

to mt.xcor
  output mt.xpos
end
copydef "xcor "mt.xcor

to mt.ycor
  output mt.ypos
end
copydef "ycor "mt.ycor

to mt.heading
  output mt.dir
end
copydef "heading "mt.heading

to mt.towards :position
  output modulo (arctan difference last :position mt.ypos
      difference first :position mt.xpos) 360
end
copydef "towards "mt.towards

to mt.pendown
  make "mt.draw "true
end
copydef "pendown "mt.pendown
copydef "pd "mt.pendown

to mt.penup
  make "mt.draw "false
  make "mt.start "true
end
copydef "penup "mt.penup
copydef "pu "mt.penup

to mt.pendownp
  output "mt.draw
end
copydef "pendownp "mt.pendownp
copydef "pendown? "mt.pendownp

to mt.arc :angle :radius
  print [arc not implemented as OSM ways are straight lines]
end
copydef "arc "mt.arc

to rect :side1 :side2
  repeat 2 [forward :side1 right 90 forward :side2 right 90]
end

to writeosm :filename
  (local "cnt "lat "lon "degnodes "minlat "minlon "maxlat "maxlon)
  openwrite :filename
  setwrite :filename
  print [<?xml version='1.0' encoding='UTF-8'?>]
  print [<osm version='0.6' generator='mapturtle'>]

  make "minlat last mt.origin
  make "minlon first mt.origin
  make "maxlat last mt.origin
  make "maxlon first mt.origin

  make "degnodes map [
    make "lat sum product last ? mt.latmetre last :mt.origin
    make "lon sum product first ? quotient mt.latmetre cos :lat first :mt.origin
    if lessp :lon :minlon [ make "minlon :lon ]
    if lessp :lat :minlat [ make "minlat :lat ]
    if greaterp :lon :maxlon [ make "maxlon :lon ]
    if greaterp :lat :maxlat [ make "maxlat :lat ]
    list :lon :lat
  ] :mt.nodes 

  (print "<bounds (word "minlat=' :minlat "') (word "minlon=' :minlon "') (word "maxlat=' :maxlat "') (word "maxlon=' :maxlon "') "origin='CGImap "0.0.2'/>)
  foreach degnodes [
    (print " " "<node (word "id=' minus # "') "action='modify' "visible='true' (word "lat=' last ? "') (word "lon=' first ? "'/>))
  ]
  make "cnt difference -1 count :mt.nodes
  foreach :mt.ways [
    (print " " "<way (word "id=' :cnt "') "action='modify' "visible='true'>)
    make "cnt difference :cnt 1
    foreach ? [
      (print " " " " "<nd (word "ref=' minus ? "'/>))
    ]
    (print " " "</way>)
  ]

  print "</osm>
  close :filename
end