OpenStreetMap

JOSM scripting plugin: be a power user!

Posted by bdiscoe on 3 March 2014 in English (English)

I've now spent a LOT of time using JOSM, and it is one of the best applications i have ever used, of any kind. With left hand on the keyboard, right on the mouse, you can do quality editing with great speed and accuracy. Advice for newbies: Install the "utilsplugin2" right now, then "buildings_tools" for buildings, and "FastDraw" for streams and ponds.

Eventually, though, you find yourself doing a lot of the same steps over again. One thing JOSM does NOT have is a "macro" ability to record and play back commands. It does, however, have a scripting plugin! (Thank you "Gubaer", author of the plugin!) I have just begun to work with its Javascript API, which has decent docs but very few examples. I will give some examples here in my diary of of scripts i've written, in case they are useful!

As a first example, renaming streets. The JOSM validator will warn you about abbreviated English street names ("Main St") but it won't automatically fix them for you. I wrote a script which does that. Just install the scripting plugin, open the scripting console, paste in this script and press "Run".

Note that this not a shining example of great code, just a rough script. As an exercise for the reader, you could extend it to also handle "Blvd" for "Boulevard".

//
// Look through all data layers, looking for abbreviated street names and
// replace them with the full string, e.g. "Rd" -> "Road".
//

var util = require("josm/util");
var command = require("josm/command");
var ScriptingConsole = org.openstreetmap.josm.plugins.scripting.ui.console.ScriptingConsole;
var console = ScriptingConsole.instance.scriptLog.logWriter;

for (i = 0; i < josm.layers.length; i++) {
    var layer = josm.layers.get(i);
    if (layer.name.substring(0, 4) != "Data")
      continue;
    var dataset = layer.data;
    var result = dataset.query("type:way");
    var renames = 0;
    console.println("number of ways: " + result.length);
    for (j = 0; j < result.length; j++) {
        var way = result[j];
        var name = way.get("name");
        if (name == null) continue;
        if (name.length() < 4) continue;

        var s = name.slice(-3);
        if (s == " Tr" || s == " rd" || s == " Ct" || s == "Ave" || s == "Cir" || s == " Dr" || s == " Rd" || s == " Ln" || s== " Pl" || s == " St" || s == "Hwy" || s == " Wy") {
          var s2 = name.slice(0, name.length() - 3);
          if (s == " Tr") s2 += " Trail";
          if (s == " rd") s2 += " Road";
          if (s == " Ct") s2 += " Court";
          if (s == "Ave") s2 += "Avenue";
          if (s == "Cir") s2 += "Circle";
          if (s == " Dr") s2 += " Drive";
          if (s == " Rd") s2 += " Road";
          if (s == " Ln") s2 += " Lane";
          if (s == " Pl") s2 += " Place";
          if (s == " St") s2 += " Street";
          if (s == "Hwy") s2 += "Highway";
          if (s == " Wy") s2 += " Way";

          console.println("  rename [" + name + "] to [" + s2 + "]");
          // create and apply a undoable/redoable command
          layer.apply( command.change(dataset.way(way.id), {tags: {name: s2}}) );
          renames++;
          way.setModified(true);
        }
    }
    console.println("renames:" + renames);
}

Comment from Zverik on 3 March 2014 at 18:44

There is also the CommandLine plugin which executes shell scripts.

Hide this comment

Comment from kenguest on 4 March 2014 at 14:18

Can I presume it isn't possible to commit changes using the plugin? I'm just a little wary of mistakes/typos being committed "by brute force".

There's irony in here somewhere, considering "my" Services_OpenStreetMap project, which does allow commits etc! :-D

Hide this comment

Comment from woodpeck on 5 March 2014 at 15:56

Note that any edit where you do not actually review the individual object - and using this script would certainly lead to such edits - counts as a "mechanical edit" which needs to be discussed beforehand (including publishing the code for others to review), and properly documented. Executing mechanical changes without these precautions might lead to a revert of the changeset in question and the user getting slapped on the wrist by DWG.

Hide this comment

Comment from bdiscoe on 6 March 2014 at 02:10

Woodpeck, this is no more of a mechanical edit than using JOSM's existing (powerful!) validation cleaning tools. For example, if you have isolated nodes, or duplicated nodes, JOSM can fix them for you in a single mouseclick. This script only provides a cleaning tool that JOSM hasn't implemented yet.

Of course, mechanical edits where visual confirmation would be needed, are bad. But, it does not take visual confirmation to rename "Main St" to "Main Street".

Hide this comment

Comment from emacsen on 7 March 2014 at 10:11

bdiscoe, as the person who wrote the bot that expanded several million way names- yes, it does require some extra step.

Your script doesn't take a lof of things into consideration- one being the location of the area!

Also, while I'd venture to say your script is safe in the US... it's something you may want to discuss anyway.

Hide this comment

Comment from bdiscoe on 17 March 2014 at 09:12

For those interested, a later version of the script which handles "blvd" etc. and is better written is available at https://drive.google.com/file/d/0B-Csp1lvUfO8RVpZbU9zTXR5Y3M/edit?usp=sharing

Hide this comment

Leave a comment

Parsed with Markdown

  • Headings

    # Heading
    ## Subheading

  • Unordered list

    * First item
    * Second item

  • Ordered list

    1. First item
    2. Second item

  • Link

    [Text](URL)
  • Image

    ![Alt text](URL)

Login to leave a comment