User:Opk
Jump to navigation
Jump to search
| Babel user information |
|---|
| Users by language |
I support the license
upgrade to ODbL v 1.0
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
