[josm-dev] Scripting plugin

Paul Hartmann phaaurlt at googlemail.com
Thu Apr 14 15:17:18 BST 2011


Jo wrote:
> I'm back on track with the scripting plugin. I created a Jython script that
> helps to find probable spelling errors in street names. It's quite specific
> in that it supports the bilingual status of Brussels.
> 
> #!/bin/jython
>> #
>> # Spell checking.py  - Helps to locate probable spell errors
>> #
>> from javax.swing import JOptionPane
>> from org.openstreetmap.josm import Main
>> import org.openstreetmap.josm.command as Command
>> import org.openstreetmap.josm.data.osm.Node as Node
>> import org.openstreetmap.josm.data.osm.Way as Way
>> import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
>> import org.openstreetmap.josm.data.osm.DataSet as DataSet
>>
>> corrections = {'fr': [('Dr. ', 'Docteur '),('R. ', 'Rue '), ('Av. ',
>> 'Avenue '), ('Bd. ', 'Boulevard '),
>>                       ('Sq.', 'Square'), ('Pl.', 'Place'),
>>                       (' De ', ' de '), (' Le ', ' le '), (' La ', ' la '),
>> (' Du ', ' du '), (' Des ', ' des '), (' Les ', ' les '),
>>                       (' Au ', ' au '),(' Aux ', ' aux '),('À', 'à'),(' Den
>> ',' den '), (" Sur ", " sur "),
>>                       (" D'"," d'"), (" L'"," l'"), ("' ","'"),
>>                       ("Ecole ","École "), ("Eglise", "Église"),
>> ("Chateau", "Château"), ("Cable", "Câble"), ("General", "Général")],
>>                'nl': [(" Voor ", " voor "), (" Op ", " op "), (" Pour ", "
>> pour "), (" Naar ", " naar "), (" Ter ", " ter "), (" En ", " en "), (" Van
>> ", " van "),
>>                       ("'T ", "'t "), ("'S ", "'s "), ("-Ter-", "-ter-"),
>> (" Het ", " het "),
>>                       (" Straat", "straat"), (" Weg", "weg"), (" Laan",
>> "laan"), (" Steenweg", "steenweg"),
>>                       (" Baan", "baan"), ("Oudebaan", "Oude Baan"),
>> ("Grotebaan", "Grote Baan"),
>>                       ("de Lijn", "De Lijn")]}
>>
>> commandsList = []
>> streetnames = {}
>>
>> def getMapView():
>>     if Main.main and Main.main.map:
>>         return Main.main.map.mapView
>>     else:
>>         return None
>>
>> def myOwnCapitalize(word):
>>     # JOptionPane.showMessageDialog(Main.parent, word.decode('utf-8'))
>>     if word:
>>         return word[0].upper() + word[1:]
>>     else:
>>         return u""
>>
>> mv = getMapView()
>>
>> if mv and mv.editLayer and mv.editLayer.data:
>>     selectedNodes = mv.editLayer.data.getSelectedNodes()
>>     selectedWays = mv.editLayer.data.getWays()
>>     selectedRelations = mv.editLayer.data.getSelectedRelations()
>>
>>     if not(selectedNodes or selectedWays or selectedRelations):
>>         JOptionPane.showMessageDialog(Main.parent, "Please select
>> something")
>>     else:
>>         for way in selectedWays:
>>             for isoLang in ['nl', 'fr', '']:
>>                 correctedName = result = u''
>>                 if isoLang:
>>                     nameColonIso = 'name:' + isoLang
>>                 else:
>>                     nameColonIso = 'name'
>>                 if way.hasKey(nameColonIso):
>>                     name=str(way.get(nameColonIso).encode('utf-8'))
>>                     if name in streetnames:
>>                         if streetnames[name] == 'ignore':
>>                             continue
>>                         else:
>>                             correctedName = streetnames[name]
>>                     else:
>>                         Main.main.getCurrentDataSet().setSelected(way)
>>                         # dummy = mv.editLayer.data.getSelected()
>>                         #
>> mv.zoomTo(Main.main.getEditLayer().data.getSelected())
>>                         # JOptionPane.showMessageDialog(Main.parent,
>> name.decode('utf-8'))
>>                         for subname in name.split(";"):
>>                             for word in subname.split(" "):
>>                                 if word:
>>                                     if "-" in word and len(word)>1:
>>                                         dashes = word.split("-")
>>
>>                                         correctedName +=
>> myOwnCapitalize(dashes[0])
>>                                         for dash in dashes[1:]:
>>                                             # if dash[0] == ' ':
>>                                                 # correctedName += u"-" +
>> myOwnCapitalize(dash[1:])
>>                                             # else:
>>                                                 correctedName += u"-" +
>> myOwnCapitalize(dash.strip())
>>                                     elif "'" in word and not("." in word):
>>                                         apo=word.split("'")
>>                                         if apo[0]: correctedName +=
>> myOwnCapitalize(apo[0])
>>                                         correctedName += "'"
>>                                         if apo[1]: correctedName +=
>> myOwnCapitalize(apo[1])
>>                                     elif "." in word or len(word)>1 and
>> word[1]==word[1].upper() or len(word)>2 and word[2]==word[2].upper():
>>                                         correctedName += word
>>                                     else:
>>                                         correctedName +=
>> myOwnCapitalize(word)
>>                                     correctedName += ' '
>>                             correctedName = correctedName.strip() + ';'
>>                         if correctedName and correctedName[-1] == ';':
>> correctedName = correctedName[0:-1]
>>                         for lang in corrections:
>>                             if isoLang and isoLang != lang:
>>                                 continue
>>                             elif not(isoLang) and way.hasKey('name:fr') and
>> way.hasKey('name:nl'):
>>                                 correctedName =
>> str(way.get('name:fr').encode('utf-8')) + ' - ' +
>> str(way.get('name:nl').encode('utf-8'))
>>                             else:
>>                                 for wrongspelling, correction in
>> corrections[lang]:
>>                                     correctedName =
>> correctedName.replace(wrongspelling, correction)
>>                         correctedName = correctedName.strip()
>>                     if name != correctedName:
>>                         try:
>>                             result =
>> JOptionPane.showInputDialog(Main.parent,
>>                                     "Previous name: " +
>> name.decode('utf-8'),
>>                                     'Change spelling?',
>>                                     JOptionPane.QUESTION_MESSAGE,
>>                                     None,
>>                                     None,
>>                                     correctedName.decode('utf-8'))
>>                         except UnicodeDecodeError:
>>                             pass
>>                         if result: result = result.strip(' -')
>>                         print
>>                         print nameColonIso
>>                         print name
>>                         print result
>>                         if not(result):
>>                             streetnames[name] = 'ignore'
>>                         elif result.lower() == u'stop':
>>                             break
>>                         else:
>>                             streetnames[name] = result
>>                             newWay = Way(way)
>>                             newWay.put(nameColonIso, result)
>>                             commandsList.append(Command.ChangeCommand(way,
>> newWay))
>>                 if commandsList:
>>
>> Main.main.undoRedo.add(Command.SequenceCommand("Spelling " + nameColonIso +
>> ' ' + result, commandsList))
>>                     commandsList = []
>>             if result and result.lower() == u'stop':
>>                 break
>>
> 
> What is important to note is that we found how to find (selected) elements,
> select elements and we also found a way to modify their tags and most
> importantly how to add the modifications to the undoRedo buffer.

Great work! Maybe you can host it somewhere, so we can link it from the wiki page of the Scripting plugin [1]. (Or simply put it in the wiki.) Also consider adding a license note, so others can use or build on your script.
 
> What I need to do now is to have a different type of dialog box, with custom
> buttons and edit fields. I want to be able to display name tags and all
> their translations at once.

I suppose you have to use swing, like you already did with JOptionPane. Personally, I would do a prototype in Java and then port it to jython. In JOSM, we have a class ExtendedDialog that adds a little more functionality to JDialog, but it shouldn't be problem with standard swing classes.

> What I also would need, is a way to determine if a way is within a given
> closedway/multipolygon. This is necessary, because within Brussels the names
> are supposed to be bilingual, whereas in Flanders they are supposed to be in
> Dutch, occasionally accompanied by a name:fr tag.
> 
> Is it possible to do that in JOSM?

This ticket [2] may be interesting, I'd simply use java.awt.geom.GeneralPath.contains(..).

[1] http://wiki.openstreetmap.org/wiki/JOSM/Plugins/Scripting
[2] http://josm.openstreetmap.de/ticket/5694

Paul



More information about the josm-dev mailing list