[[TranslatedPages(revision=17)]]
= Greffon -> Scripting -> Python =
== Objectif ==
D'autres exemples en Python :
[[PageOutline(2,Table des Matières)]]
== Convertir un chemin qui se raccorde à un carrefour giratoire non fractionné en une bifurcation. ==
Convertir un chemin qui se connecte à un carrefour giratoire en une fourche composée de 2 chemins à sens unique. En divisant le chemin sur son dernier nœud et en l'attachant aux 2 nœuds adjacents au nœud commun du chemin du carrefour giratoire. Cette version ne fonctionne que sur les carrefours giratoires non fractionnés. Voir l'exemple suivant pour une version mise à jour.
{{{#!python
from javax.swing import JOptionPane
from org.openstreetmap.josm.gui import MainApplication
import org.openstreetmap.josm.command as Command
import org.openstreetmap.josm.data.osm.Way as Way
editLayer = MainApplication.getLayerManager().getEditLayer()
if editLayer and editLayer.data:
selected_ways = editLayer.data.getSelectedWays()
print selected_ways
if not(selected_ways) or len(selected_ways)>1:
JOptionPane.showMessageDialog(MainApplication.parent,
"Veuillez sélectionner un chemin unique qui se raccorde à un carrefour giratoire")
else:
for way in selected_ways:
if way.get('oneway') in ['yes', '-1']:
JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin a un attribut - sens unique")
else:
node_before = None
node_after = None
common_node = None
common_node_becomes_node_before=None
#print dir(way)
for fln in [way.firstNode(), way.lastNode()]:
print 'fln', fln
for parentway in fln.getParentWays():
if parentway.get("junction")=='roundabout':
for n in parentway.getNodes():
if common_node:
# nous avons trouvé un nœud commun entre le chemin sélectionné et
# le chemin du carrefour giratoire dans l'itération précédente
node_after = n
# nous avons terminé ici
break
if n.getId() == fln.getId():
# c'est le nœud que le carrefour giratoire a en commun avec le chemin sélectionné
common_node = n
if not(node_before):
# normalement, nous avons rencontré un nœud du carrefour giratoire
# bien avant celui-ci, mais si le nœud commun est le premier nœud
# d'un carrefour giratoire non divisé, nous devrons prendre le dernier
# nœud du carrefour giratoire à la place
node_before = parentway.getNodes()[-2]
node_after = parentway.getNodes()[1]
break
# si ce n'est pas le cas, nous passons par la boucle une fois de plus pour mettre le prochain
# nœud dans node_after
continue
node_before = n
if common_node:
# si common_node est déjà défini à ce stade, cela signifie qu'il était
# le premier nœud du chemin sélectionné,
# il devra donc être remplacé par node_before dans le chemin sélectionné
common_node_becomes_node_before = True
adjacent_node_to_split_on = way.getNodes()[1]
break
else:
common_node_becomes_node_before = False
adjacent_node_to_split_on = way.getNodes()[-1]
if not(common_node) or common_node_becomes_node_before==None:
JOptionPane.showMessageDialog(MainApplication.parent,
"Veuillez sélectionner un chemin qui se raccorde à un carrefour giratoire")
else:
print common_node.get('name')
print node_before.get('name')
print node_after.get('name')
commandsList = []
if len(way.getNodes())>2:
# diviser le dernier segment avant le carrefour giratoire si nécessaire
commandsList.append(Command.SplitWayCommand.split(
way, [adjacent_node_to_split_on], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Séparation du chemin sélectionné", commandsList))
commandsList = []
# Après la séparation, trouvez le segment qui relie à nouveau le carrefour giratoire
for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
if common_node in waypartconnectedtoroundabout.getNodes():
break
if len(way.getNodes())==2:
if common_node == waypartconnectedtoroundabout.firstNode():
adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
else:
adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
# Il est temps de faire quelque chose
# de faire une copie du chemin
modified_way = Way(waypartconnectedtoroundabout)
# remplacer ses nœuds, de sorte qu'il se transforme en une fourche
modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
# ajouter un attribut "oneway"
modified_way.put('oneway', 'yes')
# appliquer les modifications
commandsList.append(Command.ChangeCommand(
waypartconnectedtoroundabout, modified_way))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Ajouter un attribut oneway et créer un chemin en forme de fourche", commandsList))
commandsList = []
# séparer ce chemin là où il se divise en fourche
commandsList.append(Command.SplitWayCommand.split(
waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Divisez la fourche en deux chemins", commandsList))
commandsList = []
}}}
== Convertir un chemin qui se raccorde à un carrefour giratoire fractionné en une bifurcation ==
Ce script fait la même chose que le précédent, mais il fonctionne aussi sur les carrefours giratoires dont les chemins sont séparés. Il ne s'occupe pas des relations.
{{{#!python
from javax.swing import JOptionPane
from org.openstreetmap.josm.gui import MainApplication
import org.openstreetmap.josm.command as Command
import org.openstreetmap.josm.data.osm.Way as Way
editLayer = MainApplication.getLayerManager().getEditLayer()
print '==== Fresh run ===='
if editLayer and editLayer.data:
selected_ways = editLayer.data.getSelectedWays()
print selected_ways
if not(selected_ways) or len(selected_ways)>1:
JOptionPane.showMessageDialog(MainApplication.parent, "Veuillez sélectionner un chemin unique qui se connecte à un carrefour giratoire")
else:
for way in selected_ways:
if way.get('oneway') in ['yes', '-1']:
JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin est balisé par un attribut oneway")
elif way.get('junction') in ['roundabout']:
JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin fait partie d'un carrefour giratoire")
else:
node_before = None
node_after = None
common_node = None
common_node_becomes_node_before=None
roundabout_way_before = None
roundabout_way_after = None
for fln in [way.firstNode(), way.lastNode()]:
print 'fln', fln
for parentway in fln.getParentWays():
if parentway.get("junction")=='roundabout':
print parentway.get('name')
if parentway.isClosed():
# carrefour giratoire non fractionné
for n in parentway.getNodes():
if common_node:
# noeud commun trouvé entre le chemin sélectionné
# et le carrefour giratoire dans l'itération précédente
node_after = n
print node_before.get('name')
print node_after.get('name')
# nous avons terminé ici
break
if n.getId() == fln.getId():
# c'est le nœud que le carrefour giratoire a en commun avec le chemin sélectionné
common_node = n
print common_node.get('name')
if not(node_before):
# normalement, nous avons rencontré un nœud du carrefour giratoire bien
# avant celui-ci, mais si le nœud commun est le premier nœud
# d'un carrefour giratoire non divisé, nous devrons prendre le dernier
# nœud du carrefour giratoire à la place
node_before = parentway.getNodes()[-2]
node_after = parentway.getNodes()[1]
print node_before.get('name')
print node_after.get('name')
break
# si ce n'est pas le cas, nous passons par la boucle une fois de plus pour mettre le prochain
# noeud dans node_after
continue
node_before = n
else:
# il s'agit d'un carrefour giratoire fractionné
if parentway.firstNode().getId() == fln.getId():
node_after = parentway.getNodes()[1]
roundabout_way_after = parentway
print 'node after', node_after.get('name')
else:
node_before = parentway.getNodes()[-2]
roundabout_way_before = parentway
if node_before and node_after:
common_node = fln
break
if common_node:
# si common_node est déjà défini à ce stade, cela signifie que c'était
# le premier noeud du chemin sélectionné,
# il devra donc être remplacé par node_before dans le chemin sélectionné
common_node_becomes_node_before = True
break
else:
common_node_becomes_node_before = False
if common_node.getId() == way.firstNode().getId():
adjacent_node_to_split_on = way.getNodes()[1]
else:
adjacent_node_to_split_on = way.getNodes()[-1]
if not(common_node) or ((parentway.isClosed() and common_node_becomes_node_before==None)):
JOptionPane.showMessageDialog(MainApplication.parent, "Please select a way that connects to a roundabout")
else:
commandsList = []
if len(way.getNodes())>2:
# séparer le dernier segment avant le carrefour giratoire si nécessaire
commandsList.append(Command.SplitWayCommand.split(
way, [adjacent_node_to_split_on], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Partager le chemin sélectionné", commandsList))
commandsList = []
# Après la séparation, trouvez le segment qui rejoint à nouveau le carrefour giratoire
for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
if waypartconnectedtoroundabout.get('junction') == 'roundabout':
continue
if common_node in waypartconnectedtoroundabout.getNodes():
break
if len(way.getNodes())==2:
if common_node == waypartconnectedtoroundabout.firstNode():
adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
else:
adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
# Il est temps de faire quelque chose
# faire une copie du chemin
modified_way = Way(waypartconnectedtoroundabout)
# replacer ses nœuds, il devient donc une fourche
modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
# ajouter un attribut oneway
modified_way.put('oneway', 'yes')
# appliquer les modifications
commandsList.append(Command.ChangeCommand(
waypartconnectedtoroundabout, modified_way))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Ajouter l'attribut oneway et créer un chemin en forme de fourche", commandsList))
commandsList = []
# partager ce chemin où il y a une fourche
commandsList.append(Command.SplitWayCommand.split(
waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Divisez la fourche en deux chemins", commandsList))
commandsList = []
if roundabout_way_before and roundabout_way_after:
origway = roundabout_way_before
roundabout_way_before.addNode(node_after)
commandsList.append(Command.ChangeCommand(
origway, roundabout_way_before))
origway = roundabout_way_after
roundabout_way_after.removeNode(common_node)
commandsList.append(Command.ChangeCommand(
origway,roundabout_way_after))
# middleway = Way(roundabout_way_after).setNodes(
# [node_before, common_node, node_after])
# commandsList.append(Command.AddCommand(editLayer.data, middleway))
# MainApplication.undoRedo.add(Command.SequenceCommand(
# "Ajouter un chemin sur le carrefour giratoire où la fourche s'attache", commandsList))
commandsList.append(Command.SplitWayCommand.split(
roundabout_way_before, [node_before], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"decoupe le chemin du giratoire", commandsList))
commandsList = []
}}}
== Exporter une collection d'itinéraires vers un fichier GPX Garmin ==
Exporter une collection d'itinéraires vers un fichier GPX Garmin (pas un super exemple, car je ne pense pas que nous fassions encore des relations de collection) :
{{{#!python
#!/bin/jython
'''
RWN2Garmin.py - Convertisseur de réseaux numérotés en fichiers GPX Garmin
Ce code est publié sous la licence GNU General Public License v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
Il est livré sans aucune garantie.
'''
from javax.swing import JOptionPane, JDialog
from java.awt.event import ActionListener, ActionEvent
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
import time
f = open('C:/export.gpx', 'w')
f.write('\n')
f.write('\n')
f.write('\n')
editLayer = Main.getLayerManager().getEditLayer()
if editLayer and editLayer.data:
selectedRelations = mv.editLayer.data.getSelectedRelations()
if not(selectedRelations):
JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une relation de collection")
else:
print
for collection in selectedRelations:
print 'COLLECTION:', collection
for member in collection.getMembers():
print 'MEMBER:',member
if member.isNode():
node = member.getNode()
coords = node.getCoor()
lon = coords.getX()
lat = coords.getY()
rwn_ref = node.get('rwn_ref')
f.write('\t\n')
if rwn_ref:
f.write('\t\t' + rwn_ref + '\n')
f.write('\t\n')
for member in collection.getMembers():
if member.isRelation():
routerelation = member.getRelation()
f.write('\t\n')
networkname = routerelation.get('network:name')
if not(networkname):
networkname = ''
else:
networkname += ' '
note = routerelation.get('note')
if not(note): note = ''
f.write('\t\t' + networkname + note + '\n')
f.write('\t\tOpenStreetMap.org\n')
f.write('\t\tfoot\n')
for routerelmember in routerelation.getMembers():
if routerelmember.isWay():
f.write('\t\t\n')
way=routerelmember.getWay()
for waynode in way.getNodes():
coords = waynode.getCoor()
lon = coords.getX()
lat = coords.getY()
f.write('\t\t\t \n')
f.write('\t\t\n')
f.write('\t\n')
f.write('\n')
f.close()
}}}
== Télécharger les éléments parents manquants pour l'élément sélectionné ==
{{{#!python
#!/bin/jython
'''
Ce code est publié sous la licence
"GNU General Public" v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
La GPL v2 est disponible ici :
https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
Il est livré sans aucune garantie.
Ce code illustre comment utiliser Jython pour :
* Télécharger tous les référents d'un élément
'''
from javax.swing import JOptionPane
from org.openstreetmap.josm import Main
import org.openstreetmap.josm.actions.DownloadReferrersAction as DownloadReferrersAction
editLayer = Main.getLayerManager().getEditLayer()
if editLayer and editLayer.data:
selectedElements = editLayer.data.getSelected()
if not(selectedElements):
JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner un élément")
else:
DownloadReferrersAction.downloadReferrers(editLayer, selectedElements)
}}}
== Télécharger les membres absents de la relation ==
{{{
#!/bin/jython
'''
Ce code est publié sous la licence
"GNU General Public" v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
La GPL v2 est disponible ici :
https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
Il est livré sans aucune garantie.
Ce code illustre comment utiliser Jython pour :
* Télécharger tous les membres absents de la relation
'''
from javax.swing import JOptionPane
from org.openstreetmap.josm import Main
import org.openstreetmap.josm.data.osm.Node as Node
import org.openstreetmap.josm.data.osm.Way as Way
import org.openstreetmap.josm.data.osm.Relation as Relation
import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
import org.openstreetmap.josm.data.osm.DataSet as DataSet
import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
editLayer = Main.getLayerManager().getEditLayer()
if editLayer:
selectedRelations = editLayer.data.getSelectedRelations()
if not(selectedRelations):
JOptionPane.showMessageDialog(Main.parent, "Please select a relation")
else:
for relation in selectedRelations:
if relation.hasIncompleteMembers():
#print dir(relation)
print dir(DownloadRelationMemberTask)
DownloadRelationMemberTask.run(DownloadRelationMemberTask(relation, relation.getIncompleteMembers(), editLayer ))
}}}
== Valider une relation de route rcn ==
{{{
#!/bin/jython
'''
- Validation d'une relation de route rcn
Ce code est publié sous la licence
"GNU General Public" v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
La GPL v2 est disponible ici :
https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
Il est livré sans aucune garantie.
Ce code illustre comment utiliser Jython pour :
* passer en boucle tous les membres d'une relation de route
* déterminer si le membre est un noeud, un chemin ou une relation
* ajouter/changer les propriétés d'une relation
* Supprimer les propriétés d'une relation
* Ajouter des membres à une relation
* Supprimer des membres d'une relation
* trier tous les membres en arrière
* Comment définir un élément sélectionné
'''
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.Relation as Relation
import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
import org.openstreetmap.josm.data.osm.DataSet as DataSet
import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
import re
commandsList = []
reNumberDashNumber = re.compile(r'\d+-\d+')
def getMapView():
if Main.main and Main.main.map:
return Main.main.map.mapView
else:
return None
mv = getMapView()
if mv and mv.editLayer and mv.editLayer.data:
dummy_relation = Relation()
selectedRelations = mv.editLayer.data.getSelectedRelations()
if not(selectedRelations):
JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une relation d'itinéraire")
else:
print
for route in selectedRelations:
newRelation = Relation(route)
relationChanged = False
name = route.get('name')
if name:
if reNumberDashNumber.match(name):
print 'en supprimant le nom lorsqu'il est de la forme ##-##'
newRelation.remove('name')
relationChanged = True
else:
name = ''
ref = route.get('ref')
if ref:
if reNumberDashNumber.match(ref):
print 'en supprimant ref lorsqu'elle est de la forme ##-##'
newRelation.remove('ref')
relationChanged = True
else:
ref = ''
if relationChanged:
commandsList.append(Command.ChangeCommand(route, newRelation))
Main.main.undoRedo.add(Command.SequenceCommand("Removing name and/or ref " + name + '/' + ref, commandsList))
commandsList = []
rcn_refs = []; route_relation_names = []; memberslist = []
endnodes = []; prev_endnodes = []
continuous_forward = True; continuous_backward = True
prev_role = None; prev_endnodes_before_forward = None; last_endnodes_before_backward = None
for member in route.getMembers():
if member.isWay():
role = member.getRole()
memberslist.append(member)
way = member.getWay()
#JOptionPane.showMessageDialog(Main.parent, 'way is selected')
endnodes = [way.getNode(0), way.getNode(way.nodesCount-1)]
notfoundyet = True
for endnode in endnodes:
# inventorizing of rcn_ref on end nodes
rcn_ref = endnode.get('rcn_ref')
if rcn_ref:
rcn_refs.append(int(rcn_ref))
for referrer in endnode.getReferrers():
if referrer.getType() is dummy_relation.getType():
if referrer.get('type')=='network' and referrer.get('network')=='rcn':
relname=referrer.get('name')
if relname:
route_relation_names.append(relname)
elif referrer.get('type')=='collection':
route_relation_names.append('Node not assigned to network yet')
# checking for continuity on ways
if notfoundyet:
if role:
if prev_role:
if role=='forward' and prev_role=='forward' and endnode in prev_endnodes:
notfoundyet = False
elif role=='forward' and prev_role=='backward' and endnode in last_endnodes_before_backward:
notfoundyet = False
elif role=='backward' and prev_role=='forward' and endnode in prev_endnodes:
notfoundyet = False
elif role=='backward' and prev_role=='backward' and endnode in prev_endnodes:
notfoundyet = False
else:
if role=='forward' and endnode in prev_endnodes:
notfoundyet = False
elif role=='backward' and endnode in prev_endnodes:
notfoundyet = False
else:
if prev_role:
if prev_role=='forward' and endnode in prev_endnodes:
notfoundyet = False
elif prev_role=='backward' and endnode in last_endnodes_before_backward:
notfoundyet = False
else:
if endnode in prev_endnodes:
notfoundyet = False
# Analysis of continuity of ways
if prev_endnodes and notfoundyet:
if role:
if role == 'forward':
continuous_forward = False
elif role == 'backward':
continuous_backward = False
else:
continuous_forward = False
continuous_backward = False
if role=='forward':
if not(prev_endnodes_before_forward):
prev_endnodes_before_forward = prev_endnodes
elif prev_role=='forward' and role=='backward':
if not(last_endnodes_before_backward):
last_endnodes_before_backward = prev_endnodes
elif not(role) and prev_role=='backward':
prev_endnodes_before_forward = None
prev_role = role
prev_endnodes = endnodes
# Drawing conclusions about continuity of ways
if continuous_forward:
print 'Itinéraire continu dans la direction vers devant'
else:
print 'Itinéraire PAS CONTINU dans la direction vers devant'
if continuous_backward:
print 'Itinéraire continu dans la direction vers arrière'
else:
print 'Itinéraire PAS CONTINU dans la direction vers arrière'
# Drawing conclusions about rcn_refs
print rcn_refs
if len(rcn_refs) > 1:
newRelation = Relation(route)
relationChanged = False
if rcn_refs[0] > rcn_refs[1]:
rcn_refs.sort()
print 'Inversion de l'ordre des membres'
for member in reversed(memberslist):
newRelation.addMember( newRelation.getMembersCount(), member)
newRelation.removeMember (0)
commandsList.append(Command.ChangeCommand(route, newRelation))
Main.main.undoRedo.add(Command.SequenceCommand("Flipping order of members", commandsList))
commandsList = []
note = route.get('note')
newNote = str(rcn_refs[0]).zfill(2) + '-' + str(rcn_refs[1]).zfill(2)
if not(note) or note != newNote:
if not(note): note = 'nothing'
newRelation.put('note', newNote)
relationChanged = True
commandsList.append(Command.ChangeCommand(route, newRelation))
Main.main.undoRedo.add(Command.SequenceCommand("Changing note from " + note + ' to ' + newNote, commandsList))
commandsList = []
if len(route_relation_names) > 1 and route_relation_names[0] != route_relation_names[1]:
print
print 'Il s'agit probablement d'une CONNEXION à un autre réseau'
print route_relation_names
else:
print 'moins de 2 noeuds terminaux avec rcn_ref trouvés'
}}}
[wiki:/Help/Plugin/Scripting/Python/RCN_Route_Validator]
== Suppression des chemins supplémentaires résultant d'opérations Potlatch ==
Suppression des chemins supplémentaires résultant des opérations de division des chemins de Potlatch dans le cadre des relations d'interdiction de tourner.
{{{#!python
#!/bin/jython
'''
RepairTurns.py - Suppression des chemins supplémentaires résultant des opérations de division des chemins de Potlatch dans le cadre des relations d'interdiction de tourner
Ce code est publié sous la licence
"GNU General Public" v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
Il est livré sans aucune garantie.
Ce code parcourt en boucle les relations d'interdiction de tourner sélectionnées, en essayant de supprimer les chemins divisés à l'origine de la même manière (avec des rôles to / from) sous les relations dinterdiction de tourner qui ne devraient plus rester membres de ces relations, à la suite d'un problème de Potlatch : https://trac.openstreetmap.org/ticket/3254.
Ne fonctionne que pour les interdiction de tourner avec un noeud via
e.g. Original : from: Way1, via: Node, to:Way2
Split : from: Way1a, from: Way1b, via: Node, to: Way2
After running : from: Way1b, via: Node, to: Way2
Ce code illustre comment utiliser Jython pour :
* traiter les éléments sélectionnés
* télécharger les primitives manquantes dans le même thread (blocage)
* traiter, valider et supprimer des membres de relations
'''
from javax.swing import JOptionPane
from org.openstreetmap.josm import Main
import org.openstreetmap.josm.data.osm.Node as Node
import org.openstreetmap.josm.data.osm.Way as Way
import org.openstreetmap.josm.data.osm.Relation as Relation
import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
import org.openstreetmap.josm.data.osm.DataSet as DataSet
import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
import org.openstreetmap.josm.io.MultiFetchServerObjectReader as MultiFetchServerObjectReader
import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor as PleaseWaitProgressMonitor
import org.openstreetmap.josm.command as Command
class RestrictionError(Exception):
pass
def getMembers (restriction):
memberlist = dict()
for member in restriction.getMembers():
memberRole = member.getRole()
if memberRole == "via":
if member.isNode() and not "via" in memberlist:
memberlist[memberRole] = [member]
else:
raise RestrictionError, "Plus d'un avec rôle via ou avec via mais ce n'est pas un nœud"
elif memberRole in ("from", "to"):
if member.isWay():
try:
memberlist[memberRole].append (member)
except KeyError:
memberlist[memberRole] = [member]
else:
raise RestrictionError, "avec le rôle From ou to mais n'est pas un chemin"
else:
raise RestrictionError, "Rôle inconnu " + memberRole
if len(memberlist.keys())<3:
raise RestrictionError, "Certains rôles manquent : Seulement " + ",".join (memberlist.keys()) + " found"
return memberlist
def downloadPrimitives (primitives, editlayer):
"""
Télécharger une liste de primitives depuis le serveur, et les fusionner dans editlayer.
Blocking.
"""
monitor = PleaseWaitProgressMonitor()
monitor.showForegroundDialog()
print "Téléchargement"
try:
objectReader = MultiFetchServerObjectReader().append (primitives)
dataSet = objectReader.parseOsm (monitor)
editlayer.mergeFrom (dataSet)
editlayer.onPostDownloadFromServer()
if (not objectReader.getMissingPrimitives().isEmpty()) :
raise RestrictionError, "Impossible de télécharger les primitives manquantes"
print "Téléchargement terminé"
finally:
monitor.close()
def checkIfConnected (node, way, reverse):
"""
Return (connecté, prochain nœud à comparer (c'est-à-dire l'autre extrémité du nœud) si vrai)
"""
if (way.isOneway() != 0 and reverse):
return node == way.lastNode(True), way.firstNode(True) # True: auto process case whan isOneway == -1
if (way.isOneway() != 0): # pas d'inversion
return node == way.firstNode(True), way.lastNode(True)
if node == way.firstNode():
return True, way.lastNode()
if node == way.lastNode():
return True, way.firstNode()
return False, node
def repairrestriction (relation, memberlist, editLayer):
"""
Télécharger les membres manquants si nécessaire, obtenir la liste des membres à supprimer, et les supprimer si aucune erreur n'a été soulevée pendant la vérification
"""
incompleteMembers = relation.getIncompleteMembers()
if incompleteMembers:
downloadPrimitives (incompleteMembers, editLayer);
fromRemovalList = []; toRemovalList = []
if len (memberlist["from"]) >= 1:
currnode = memberlist["via"][0].getNode()
firstMember = True
failed = False;
# trace "from" des membres pour confirmer s'ils sont séparés d'un seul chemin
for member in reversed(memberlist['from']):
connected, currnode = checkIfConnected (currnode, member.getWay(), True)
if not connected:
if not firstMember:
raise RestrictionError, "des chemins non continus du noeud via"
failed = True
break
if not firstMember:
fromRemovalList.append (member)
else:
firstMember = False
if failed: # Deuxième tentative en cas d'inversion de la séquence lors du fractionnement
currnode = memberlist["via"][0].getNode()
for member in memberlist['from']:
connected, currnode = checkIfConnected (currnode, member.getWay(), True)
if not connected:
raise RestrictionError, "des chemins non continus du noeud via"
if not firstMember:
fromRemovalList.append (member)
else:
firstMember = False
if len (memberlist["to"]) >= 1:
currnode = memberlist["via"][0].getNode()
firstMember = True
failed = False
# trace les membres " to " pour confirmer s'ils ont été séparés d'un chemin
for member in memberlist['to']:
connected, currnode = checkIfConnected (currnode, member.getWay(), False)
if not connected:
if not firstMember:
raise RestrictionError, "chemins to non continus avec le noeud via"
failed = True
break
if not firstMember:
toRemovalList.append (member)
else:
firstMember = False
if failed: # Deuxième tentative en cas d'inversion de la séquence lors du fractionnement
currnode = memberlist["via"][0].getNode()
for member in reversed(memberlist['to']):
connected, currnode = checkIfConnected (currnode, member.getWay(), False)
if not connected:
raise RestrictionError, "chemins to non continus avec le noeud via"
if not firstMember:
toRemovalList.append (member)
else:
firstMember = False
# pour supprimer les chemins dans fromRemovalList, toRemovalList
newRelation = Relation(relation)
waysToRemove = set()
for removalList in [fromRemovalList, toRemovalList]:
waysToRemove |= set ([m.getWay() for m in removalList])
newRelation.removeMembersFor (waysToRemove)
print "Supprimer le(s) chemin(s) identifiant : " + ",".join ([str(w.getId()) for w in waysToRemove])
return Command.ChangeCommand (relation, newRelation)
validrestrictiontypes = ('only_straight_on', 'only_right_turn', 'only_left_turn', 'no_right_turn', 'no_left_turn', 'no_straight_on', 'no_u_turn')
editLayer = Main.getLayerManager().getEditLayer()
if editLayer and editLayer.data:
selectedRelations = editLayer.data.getSelectedRelations()
if not(selectedRelations):
JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une ou plusieurs relations")
else:
commandsList = []
for relation in selectedRelations:
if relation.get('type') == "restriction" and relation.get('restriction') in validrestrictiontypes:
try:
memberlist = getMembers (relation)
if (len (memberlist["from"])) > 1 or (len (memberlist["to"])) > 1 :
# Tentative de réparation
print "Tentative de réparation",
print "relation id: " + str(relation.getId())
command = repairrestriction (relation, memberlist, mv.editLayer)
print "Succès"
commandsList.append (command)
except RestrictionError, e:
print str(e), "; relation id: "+ str(relation.getId())
Main.main.undoRedo.add(Command.SequenceCommand("Réparation des interdictions de tourner", commandsList))
commandsList=[]
}}}
== Voir également ==
* La version originale de cette page en [wiki:/Help/Plugin/Scripting/Python anglais]
----
Retour au [wikitr:/Help/Plugin/Scripting Greffon Scripting] \\
Retour à l'[wikitr:/Plugins Aide des Greffons] \\
Retour à l'[wikitr:/Help Aide Principale][[TranslatedPages(revision=17)]]
= Greffon -> Scripting -> Python =
== Objectif ==
D'autres exemples en Python :
[[PageOutline(2,Table des Matières)]]
== Convertir un chemin qui se raccorde à un carrefour giratoire non fractionné en une bifurcation. ==
Convertir un chemin qui se connecte à un carrefour giratoire en une fourche composée de 2 chemins à sens unique. En divisant le chemin sur son dernier nœud et en l'attachant aux 2 nœuds adjacents au nœud commun du chemin du carrefour giratoire. Cette version ne fonctionne que sur les carrefours giratoires non fractionnés. Voir l'exemple suivant pour une version mise à jour.
{{{#!python
from javax.swing import JOptionPane
from org.openstreetmap.josm.gui import MainApplication
import org.openstreetmap.josm.command as Command
import org.openstreetmap.josm.data.osm.Way as Way
editLayer = MainApplication.getLayerManager().getEditLayer()
if editLayer and editLayer.data:
selected_ways = editLayer.data.getSelectedWays()
print selected_ways
if not(selected_ways) or len(selected_ways)>1:
JOptionPane.showMessageDialog(MainApplication.parent,
"Veuillez sélectionner un chemin unique qui se raccorde à un carrefour giratoire")
else:
for way in selected_ways:
if way.get('oneway') in ['yes', '-1']:
JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin a un attribut - sens unique")
else:
node_before = None
node_after = None
common_node = None
common_node_becomes_node_before=None
#print dir(way)
for fln in [way.firstNode(), way.lastNode()]:
print 'fln', fln
for parentway in fln.getParentWays():
if parentway.get("junction")=='roundabout':
for n in parentway.getNodes():
if common_node:
# nous avons trouvé un nœud commun entre le chemin sélectionné et
# le chemin du carrefour giratoire dans l'itération précédente
node_after = n
# nous avons terminé ici
break
if n.getId() == fln.getId():
# c'est le nœud que le carrefour giratoire a en commun avec le chemin sélectionné
common_node = n
if not(node_before):
# normalement, nous avons rencontré un nœud du carrefour giratoire
# bien avant celui-ci, mais si le nœud commun est le premier nœud
# d'un carrefour giratoire non divisé, nous devrons prendre le dernier
# nœud du carrefour giratoire à la place
node_before = parentway.getNodes()[-2]
node_after = parentway.getNodes()[1]
break
# si ce n'est pas le cas, nous passons par la boucle une fois de plus pour mettre le prochain
# nœud dans node_after
continue
node_before = n
if common_node:
# si common_node est déjà défini à ce stade, cela signifie qu'il était
# le premier nœud du chemin sélectionné,
# il devra donc être remplacé par node_before dans le chemin sélectionné
common_node_becomes_node_before = True
adjacent_node_to_split_on = way.getNodes()[1]
break
else:
common_node_becomes_node_before = False
adjacent_node_to_split_on = way.getNodes()[-1]
if not(common_node) or common_node_becomes_node_before==None:
JOptionPane.showMessageDialog(MainApplication.parent,
"Veuillez sélectionner un chemin qui se raccorde à un carrefour giratoire")
else:
print common_node.get('name')
print node_before.get('name')
print node_after.get('name')
commandsList = []
if len(way.getNodes())>2:
# diviser le dernier segment avant le carrefour giratoire si nécessaire
commandsList.append(Command.SplitWayCommand.split(
way, [adjacent_node_to_split_on], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Séparation du chemin sélectionné", commandsList))
commandsList = []
# Après la séparation, trouvez le segment qui relie à nouveau le carrefour giratoire
for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
if common_node in waypartconnectedtoroundabout.getNodes():
break
if len(way.getNodes())==2:
if common_node == waypartconnectedtoroundabout.firstNode():
adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
else:
adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
# Il est temps de faire quelque chose
# de faire une copie du chemin
modified_way = Way(waypartconnectedtoroundabout)
# remplacer ses nœuds, de sorte qu'il se transforme en une fourche
modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
# ajouter un attribut "oneway"
modified_way.put('oneway', 'yes')
# appliquer les modifications
commandsList.append(Command.ChangeCommand(
waypartconnectedtoroundabout, modified_way))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Ajouter un attribut oneway et créer un chemin en forme de fourche", commandsList))
commandsList = []
# séparer ce chemin là où il se divise en fourche
commandsList.append(Command.SplitWayCommand.split(
waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Divisez la fourche en deux chemins", commandsList))
commandsList = []
}}}
== Convertir un chemin qui se raccorde à un carrefour giratoire fractionné en une bifurcation ==
Ce script fait la même chose que le précédent, mais il fonctionne aussi sur les carrefours giratoires dont les chemins sont séparés. Il ne s'occupe pas des relations.
{{{#!python
from javax.swing import JOptionPane
from org.openstreetmap.josm.gui import MainApplication
import org.openstreetmap.josm.command as Command
import org.openstreetmap.josm.data.osm.Way as Way
editLayer = MainApplication.getLayerManager().getEditLayer()
print '==== Fresh run ===='
if editLayer and editLayer.data:
selected_ways = editLayer.data.getSelectedWays()
print selected_ways
if not(selected_ways) or len(selected_ways)>1:
JOptionPane.showMessageDialog(MainApplication.parent, "Veuillez sélectionner un chemin unique qui se connecte à un carrefour giratoire")
else:
for way in selected_ways:
if way.get('oneway') in ['yes', '-1']:
JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin est balisé par un attribut oneway")
elif way.get('junction') in ['roundabout']:
JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin fait partie d'un carrefour giratoire")
else:
node_before = None
node_after = None
common_node = None
common_node_becomes_node_before=None
roundabout_way_before = None
roundabout_way_after = None
for fln in [way.firstNode(), way.lastNode()]:
print 'fln', fln
for parentway in fln.getParentWays():
if parentway.get("junction")=='roundabout':
print parentway.get('name')
if parentway.isClosed():
# carrefour giratoire non fractionné
for n in parentway.getNodes():
if common_node:
# noeud commun trouvé entre le chemin sélectionné
# et le carrefour giratoire dans l'itération précédente
node_after = n
print node_before.get('name')
print node_after.get('name')
# nous avons terminé ici
break
if n.getId() == fln.getId():
# c'est le nœud que le carrefour giratoire a en commun avec le chemin sélectionné
common_node = n
print common_node.get('name')
if not(node_before):
# normalement, nous avons rencontré un nœud du carrefour giratoire bien
# avant celui-ci, mais si le nœud commun est le premier nœud
# d'un carrefour giratoire non divisé, nous devrons prendre le dernier
# nœud du carrefour giratoire à la place
node_before = parentway.getNodes()[-2]
node_after = parentway.getNodes()[1]
print node_before.get('name')
print node_after.get('name')
break
# si ce n'est pas le cas, nous passons par la boucle une fois de plus pour mettre le prochain
# noeud dans node_after
continue
node_before = n
else:
# il s'agit d'un carrefour giratoire fractionné
if parentway.firstNode().getId() == fln.getId():
node_after = parentway.getNodes()[1]
roundabout_way_after = parentway
print 'node after', node_after.get('name')
else:
node_before = parentway.getNodes()[-2]
roundabout_way_before = parentway
if node_before and node_after:
common_node = fln
break
if common_node:
# si common_node est déjà défini à ce stade, cela signifie que c'était
# le premier noeud du chemin sélectionné,
# il devra donc être remplacé par node_before dans le chemin sélectionné
common_node_becomes_node_before = True
break
else:
common_node_becomes_node_before = False
if common_node.getId() == way.firstNode().getId():
adjacent_node_to_split_on = way.getNodes()[1]
else:
adjacent_node_to_split_on = way.getNodes()[-1]
if not(common_node) or ((parentway.isClosed() and common_node_becomes_node_before==None)):
JOptionPane.showMessageDialog(MainApplication.parent, "Please select a way that connects to a roundabout")
else:
commandsList = []
if len(way.getNodes())>2:
# séparer le dernier segment avant le carrefour giratoire si nécessaire
commandsList.append(Command.SplitWayCommand.split(
way, [adjacent_node_to_split_on], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Partager le chemin sélectionné", commandsList))
commandsList = []
# Après la séparation, trouvez le segment qui rejoint à nouveau le carrefour giratoire
for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
if waypartconnectedtoroundabout.get('junction') == 'roundabout':
continue
if common_node in waypartconnectedtoroundabout.getNodes():
break
if len(way.getNodes())==2:
if common_node == waypartconnectedtoroundabout.firstNode():
adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
else:
adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
# Il est temps de faire quelque chose
# faire une copie du chemin
modified_way = Way(waypartconnectedtoroundabout)
# replacer ses nœuds, il devient donc une fourche
modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
# ajouter un attribut oneway
modified_way.put('oneway', 'yes')
# appliquer les modifications
commandsList.append(Command.ChangeCommand(
waypartconnectedtoroundabout, modified_way))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Ajouter l'attribut oneway et créer un chemin en forme de fourche", commandsList))
commandsList = []
# partager ce chemin où il y a une fourche
commandsList.append(Command.SplitWayCommand.split(
waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"Divisez la fourche en deux chemins", commandsList))
commandsList = []
if roundabout_way_before and roundabout_way_after:
origway = roundabout_way_before
roundabout_way_before.addNode(node_after)
commandsList.append(Command.ChangeCommand(
origway, roundabout_way_before))
origway = roundabout_way_after
roundabout_way_after.removeNode(common_node)
commandsList.append(Command.ChangeCommand(
origway,roundabout_way_after))
# middleway = Way(roundabout_way_after).setNodes(
# [node_before, common_node, node_after])
# commandsList.append(Command.AddCommand(editLayer.data, middleway))
# MainApplication.undoRedo.add(Command.SequenceCommand(
# "Ajouter un chemin sur le carrefour giratoire où la fourche s'attache", commandsList))
commandsList.append(Command.SplitWayCommand.split(
roundabout_way_before, [node_before], []))
MainApplication.undoRedo.add(Command.SequenceCommand(
"decoupe le chemin du giratoire", commandsList))
commandsList = []
}}}
== Exporter une collection d'itinéraires vers un fichier GPX Garmin ==
Exporter une collection d'itinéraires vers un fichier GPX Garmin (pas un super exemple, car je ne pense pas que nous fassions encore des relations de collection) :
{{{#!python
#!/bin/jython
'''
RWN2Garmin.py - Convertisseur de réseaux numérotés en fichiers GPX Garmin
Ce code est publié sous la licence GNU General Public License v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
Il est livré sans aucune garantie.
'''
from javax.swing import JOptionPane, JDialog
from java.awt.event import ActionListener, ActionEvent
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
import time
f = open('C:/export.gpx', 'w')
f.write('\n')
f.write('\n')
f.write('\n')
editLayer = Main.getLayerManager().getEditLayer()
if editLayer and editLayer.data:
selectedRelations = mv.editLayer.data.getSelectedRelations()
if not(selectedRelations):
JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une relation de collection")
else:
print
for collection in selectedRelations:
print 'COLLECTION:', collection
for member in collection.getMembers():
print 'MEMBER:',member
if member.isNode():
node = member.getNode()
coords = node.getCoor()
lon = coords.getX()
lat = coords.getY()
rwn_ref = node.get('rwn_ref')
f.write('\t\n')
if rwn_ref:
f.write('\t\t' + rwn_ref + '\n')
f.write('\t\n')
for member in collection.getMembers():
if member.isRelation():
routerelation = member.getRelation()
f.write('\t\n')
networkname = routerelation.get('network:name')
if not(networkname):
networkname = ''
else:
networkname += ' '
note = routerelation.get('note')
if not(note): note = ''
f.write('\t\t' + networkname + note + '\n')
f.write('\t\tOpenStreetMap.org\n')
f.write('\t\tfoot\n')
for routerelmember in routerelation.getMembers():
if routerelmember.isWay():
f.write('\t\t\n')
way=routerelmember.getWay()
for waynode in way.getNodes():
coords = waynode.getCoor()
lon = coords.getX()
lat = coords.getY()
f.write('\t\t\t \n')
f.write('\t\t\n')
f.write('\t\n')
f.write('\n')
f.close()
}}}
== Télécharger les éléments parents manquants pour l'élément sélectionné ==
{{{#!python
#!/bin/jython
'''
Ce code est publié sous la licence
"GNU General Public" v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
La GPL v2 est disponible ici :
https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
Il est livré sans aucune garantie.
Ce code illustre comment utiliser Jython pour :
* Télécharger tous les référents d'un élément
'''
from javax.swing import JOptionPane
from org.openstreetmap.josm import Main
import org.openstreetmap.josm.actions.DownloadReferrersAction as DownloadReferrersAction
editLayer = Main.getLayerManager().getEditLayer()
if editLayer and editLayer.data:
selectedElements = editLayer.data.getSelected()
if not(selectedElements):
JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner un élément")
else:
DownloadReferrersAction.downloadReferrers(editLayer, selectedElements)
}}}
== Télécharger les membres absents de la relation ==
{{{
#!/bin/jython
'''
Ce code est publié sous la licence
"GNU General Public" v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
La GPL v2 est disponible ici :
https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
Il est livré sans aucune garantie.
Ce code illustre comment utiliser Jython pour :
* Télécharger tous les membres absents de la relation
'''
from javax.swing import JOptionPane
from org.openstreetmap.josm import Main
import org.openstreetmap.josm.data.osm.Node as Node
import org.openstreetmap.josm.data.osm.Way as Way
import org.openstreetmap.josm.data.osm.Relation as Relation
import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
import org.openstreetmap.josm.data.osm.DataSet as DataSet
import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
editLayer = Main.getLayerManager().getEditLayer()
if editLayer:
selectedRelations = editLayer.data.getSelectedRelations()
if not(selectedRelations):
JOptionPane.showMessageDialog(Main.parent, "Please select a relation")
else:
for relation in selectedRelations:
if relation.hasIncompleteMembers():
#print dir(relation)
print dir(DownloadRelationMemberTask)
DownloadRelationMemberTask.run(DownloadRelationMemberTask(relation, relation.getIncompleteMembers(), editLayer ))
}}}
== Valider une relation de route rcn ==
{{{
#!/bin/jython
'''
- Validation d'une relation de route rcn
Ce code est publié sous la licence
"GNU General Public" v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
La GPL v2 est disponible ici :
https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
Il est livré sans aucune garantie.
Ce code illustre comment utiliser Jython pour :
* passer en boucle tous les membres d'une relation de route
* déterminer si le membre est un noeud, un chemin ou une relation
* ajouter/changer les propriétés d'une relation
* Supprimer les propriétés d'une relation
* Ajouter des membres à une relation
* Supprimer des membres d'une relation
* trier tous les membres en arrière
* Comment définir un élément sélectionné
'''
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.Relation as Relation
import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
import org.openstreetmap.josm.data.osm.DataSet as DataSet
import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
import re
commandsList = []
reNumberDashNumber = re.compile(r'\d+-\d+')
def getMapView():
if Main.main and Main.main.map:
return Main.main.map.mapView
else:
return None
mv = getMapView()
if mv and mv.editLayer and mv.editLayer.data:
dummy_relation = Relation()
selectedRelations = mv.editLayer.data.getSelectedRelations()
if not(selectedRelations):
JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une relation d'itinéraire")
else:
print
for route in selectedRelations:
newRelation = Relation(route)
relationChanged = False
name = route.get('name')
if name:
if reNumberDashNumber.match(name):
print 'en supprimant le nom lorsqu'il est de la forme ##-##'
newRelation.remove('name')
relationChanged = True
else:
name = ''
ref = route.get('ref')
if ref:
if reNumberDashNumber.match(ref):
print 'en supprimant ref lorsqu'elle est de la forme ##-##'
newRelation.remove('ref')
relationChanged = True
else:
ref = ''
if relationChanged:
commandsList.append(Command.ChangeCommand(route, newRelation))
Main.main.undoRedo.add(Command.SequenceCommand("Removing name and/or ref " + name + '/' + ref, commandsList))
commandsList = []
rcn_refs = []; route_relation_names = []; memberslist = []
endnodes = []; prev_endnodes = []
continuous_forward = True; continuous_backward = True
prev_role = None; prev_endnodes_before_forward = None; last_endnodes_before_backward = None
for member in route.getMembers():
if member.isWay():
role = member.getRole()
memberslist.append(member)
way = member.getWay()
#JOptionPane.showMessageDialog(Main.parent, 'way is selected')
endnodes = [way.getNode(0), way.getNode(way.nodesCount-1)]
notfoundyet = True
for endnode in endnodes:
# inventorizing of rcn_ref on end nodes
rcn_ref = endnode.get('rcn_ref')
if rcn_ref:
rcn_refs.append(int(rcn_ref))
for referrer in endnode.getReferrers():
if referrer.getType() is dummy_relation.getType():
if referrer.get('type')=='network' and referrer.get('network')=='rcn':
relname=referrer.get('name')
if relname:
route_relation_names.append(relname)
elif referrer.get('type')=='collection':
route_relation_names.append('Node not assigned to network yet')
# checking for continuity on ways
if notfoundyet:
if role:
if prev_role:
if role=='forward' and prev_role=='forward' and endnode in prev_endnodes:
notfoundyet = False
elif role=='forward' and prev_role=='backward' and endnode in last_endnodes_before_backward:
notfoundyet = False
elif role=='backward' and prev_role=='forward' and endnode in prev_endnodes:
notfoundyet = False
elif role=='backward' and prev_role=='backward' and endnode in prev_endnodes:
notfoundyet = False
else:
if role=='forward' and endnode in prev_endnodes:
notfoundyet = False
elif role=='backward' and endnode in prev_endnodes:
notfoundyet = False
else:
if prev_role:
if prev_role=='forward' and endnode in prev_endnodes:
notfoundyet = False
elif prev_role=='backward' and endnode in last_endnodes_before_backward:
notfoundyet = False
else:
if endnode in prev_endnodes:
notfoundyet = False
# Analysis of continuity of ways
if prev_endnodes and notfoundyet:
if role:
if role == 'forward':
continuous_forward = False
elif role == 'backward':
continuous_backward = False
else:
continuous_forward = False
continuous_backward = False
if role=='forward':
if not(prev_endnodes_before_forward):
prev_endnodes_before_forward = prev_endnodes
elif prev_role=='forward' and role=='backward':
if not(last_endnodes_before_backward):
last_endnodes_before_backward = prev_endnodes
elif not(role) and prev_role=='backward':
prev_endnodes_before_forward = None
prev_role = role
prev_endnodes = endnodes
# Drawing conclusions about continuity of ways
if continuous_forward:
print 'Itinéraire continu dans la direction vers devant'
else:
print 'Itinéraire PAS CONTINU dans la direction vers devant'
if continuous_backward:
print 'Itinéraire continu dans la direction vers arrière'
else:
print 'Itinéraire PAS CONTINU dans la direction vers arrière'
# Drawing conclusions about rcn_refs
print rcn_refs
if len(rcn_refs) > 1:
newRelation = Relation(route)
relationChanged = False
if rcn_refs[0] > rcn_refs[1]:
rcn_refs.sort()
print 'Inversion de l'ordre des membres'
for member in reversed(memberslist):
newRelation.addMember( newRelation.getMembersCount(), member)
newRelation.removeMember (0)
commandsList.append(Command.ChangeCommand(route, newRelation))
Main.main.undoRedo.add(Command.SequenceCommand("Flipping order of members", commandsList))
commandsList = []
note = route.get('note')
newNote = str(rcn_refs[0]).zfill(2) + '-' + str(rcn_refs[1]).zfill(2)
if not(note) or note != newNote:
if not(note): note = 'nothing'
newRelation.put('note', newNote)
relationChanged = True
commandsList.append(Command.ChangeCommand(route, newRelation))
Main.main.undoRedo.add(Command.SequenceCommand("Changing note from " + note + ' to ' + newNote, commandsList))
commandsList = []
if len(route_relation_names) > 1 and route_relation_names[0] != route_relation_names[1]:
print
print 'Il s'agit probablement d'une CONNEXION à un autre réseau'
print route_relation_names
else:
print 'moins de 2 noeuds terminaux avec rcn_ref trouvés'
}}}
[wiki:/Help/Plugin/Scripting/Python/RCN_Route_Validator]
== Suppression des chemins supplémentaires résultant d'opérations Potlatch ==
Suppression des chemins supplémentaires résultant des opérations de division des chemins de Potlatch dans le cadre des relations d'interdiction de tourner.
{{{#!python
#!/bin/jython
'''
RepairTurns.py - Suppression des chemins supplémentaires résultant des opérations de division des chemins de Potlatch dans le cadre des relations d'interdiction de tourner
Ce code est publié sous la licence
"GNU General Public" v2 ou ultérieure.
La GPL v3 est disponible ici :
https://www.gnu.org/licenses/gpl.html
Il est livré sans aucune garantie.
Ce code parcourt en boucle les relations d'interdiction de tourner sélectionnées, en essayant de supprimer les chemins divisés à l'origine de la même manière (avec des rôles to / from) sous les relations dinterdiction de tourner qui ne devraient plus rester membres de ces relations, à la suite d'un problème de Potlatch : https://trac.openstreetmap.org/ticket/3254.
Ne fonctionne que pour les interdiction de tourner avec un noeud via
e.g. Original : from: Way1, via: Node, to:Way2
Split : from: Way1a, from: Way1b, via: Node, to: Way2
After running : from: Way1b, via: Node, to: Way2
Ce code illustre comment utiliser Jython pour :
* traiter les éléments sélectionnés
* télécharger les primitives manquantes dans le même thread (blocage)
* traiter, valider et supprimer des membres de relations
'''
from javax.swing import JOptionPane
from org.openstreetmap.josm import Main
import org.openstreetmap.josm.data.osm.Node as Node
import org.openstreetmap.josm.data.osm.Way as Way
import org.openstreetmap.josm.data.osm.Relation as Relation
import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
import org.openstreetmap.josm.data.osm.DataSet as DataSet
import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
import org.openstreetmap.josm.io.MultiFetchServerObjectReader as MultiFetchServerObjectReader
import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor as PleaseWaitProgressMonitor
import org.openstreetmap.josm.command as Command
class RestrictionError(Exception):
pass
def getMembers (restriction):
memberlist = dict()
for member in restriction.getMembers():
memberRole = member.getRole()
if memberRole == "via":
if member.isNode() and not "via" in memberlist:
memberlist[memberRole] = [member]
else:
raise RestrictionError, "Plus d'un avec rôle via ou avec via mais ce n'est pas un nœud"
elif memberRole in ("from", "to"):
if member.isWay():
try:
memberlist[memberRole].append (member)
except KeyError:
memberlist[memberRole] = [member]
else:
raise RestrictionError, "avec le rôle From ou to mais n'est pas un chemin"
else:
raise RestrictionError, "Rôle inconnu " + memberRole
if len(memberlist.keys())<3:
raise RestrictionError, "Certains rôles manquent : Seulement " + ",".join (memberlist.keys()) + " found"
return memberlist
def downloadPrimitives (primitives, editlayer):
"""
Télécharger une liste de primitives depuis le serveur, et les fusionner dans editlayer.
Blocking.
"""
monitor = PleaseWaitProgressMonitor()
monitor.showForegroundDialog()
print "Téléchargement"
try:
objectReader = MultiFetchServerObjectReader().append (primitives)
dataSet = objectReader.parseOsm (monitor)
editlayer.mergeFrom (dataSet)
editlayer.onPostDownloadFromServer()
if (not objectReader.getMissingPrimitives().isEmpty()) :
raise RestrictionError, "Impossible de télécharger les primitives manquantes"
print "Téléchargement terminé"
finally:
monitor.close()
def checkIfConnected (node, way, reverse):
"""
Return (connecté, prochain nœud à comparer (c'est-à-dire l'autre extrémité du nœud) si vrai)
"""
if (way.isOneway() != 0 and reverse):
return node == way.lastNode(True), way.firstNode(True) # True: auto process case whan isOneway == -1
if (way.isOneway() != 0): # pas d'inversion
return node == way.firstNode(True), way.lastNode(True)
if node == way.firstNode():
return True, way.lastNode()
if node == way.lastNode():
return True, way.firstNode()
return False, node
def repairrestriction (relation, memberlist, editLayer):
"""
Télécharger les membres manquants si nécessaire, obtenir la liste des membres à supprimer, et les supprimer si aucune erreur n'a été soulevée pendant la vérification
"""
incompleteMembers = relation.getIncompleteMembers()
if incompleteMembers:
downloadPrimitives (incompleteMembers, editLayer);
fromRemovalList = []; toRemovalList = []
if len (memberlist["from"]) >= 1:
currnode = memberlist["via"][0].getNode()
firstMember = True
failed = False;
# trace "from" des membres pour confirmer s'ils sont séparés d'un seul chemin
for member in reversed(memberlist['from']):
connected, currnode = checkIfConnected (currnode, member.getWay(), True)
if not connected:
if not firstMember:
raise RestrictionError, "des chemins non continus du noeud via"
failed = True
break
if not firstMember:
fromRemovalList.append (member)
else:
firstMember = False
if failed: # Deuxième tentative en cas d'inversion de la séquence lors du fractionnement
currnode = memberlist["via"][0].getNode()
for member in memberlist['from']:
connected, currnode = checkIfConnected (currnode, member.getWay(), True)
if not connected:
raise RestrictionError, "des chemins non continus du noeud via"
if not firstMember:
fromRemovalList.append (member)
else:
firstMember = False
if len (memberlist["to"]) >= 1:
currnode = memberlist["via"][0].getNode()
firstMember = True
failed = False
# trace les membres " to " pour confirmer s'ils ont été séparés d'un chemin
for member in memberlist['to']:
connected, currnode = checkIfConnected (currnode, member.getWay(), False)
if not connected:
if not firstMember:
raise RestrictionError, "chemins to non continus avec le noeud via"
failed = True
break
if not firstMember:
toRemovalList.append (member)
else:
firstMember = False
if failed: # Deuxième tentative en cas d'inversion de la séquence lors du fractionnement
currnode = memberlist["via"][0].getNode()
for member in reversed(memberlist['to']):
connected, currnode = checkIfConnected (currnode, member.getWay(), False)
if not connected:
raise RestrictionError, "chemins to non continus avec le noeud via"
if not firstMember:
toRemovalList.append (member)
else:
firstMember = False
# pour supprimer les chemins dans fromRemovalList, toRemovalList
newRelation = Relation(relation)
waysToRemove = set()
for removalList in [fromRemovalList, toRemovalList]:
waysToRemove |= set ([m.getWay() for m in removalList])
newRelation.removeMembersFor (waysToRemove)
print "Supprimer le(s) chemin(s) identifiant : " + ",".join ([str(w.getId()) for w in waysToRemove])
return Command.ChangeCommand (relation, newRelation)
validrestrictiontypes = ('only_straight_on', 'only_right_turn', 'only_left_turn', 'no_right_turn', 'no_left_turn', 'no_straight_on', 'no_u_turn')
editLayer = Main.getLayerManager().getEditLayer()
if editLayer and editLayer.data:
selectedRelations = editLayer.data.getSelectedRelations()
if not(selectedRelations):
JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une ou plusieurs relations")
else:
commandsList = []
for relation in selectedRelations:
if relation.get('type') == "restriction" and relation.get('restriction') in validrestrictiontypes:
try:
memberlist = getMembers (relation)
if (len (memberlist["from"])) > 1 or (len (memberlist["to"])) > 1 :
# Tentative de réparation
print "Tentative de réparation",
print "relation id: " + str(relation.getId())
command = repairrestriction (relation, memberlist, mv.editLayer)
print "Succès"
commandsList.append (command)
except RestrictionError, e:
print str(e), "; relation id: "+ str(relation.getId())
Main.main.undoRedo.add(Command.SequenceCommand("Réparation des interdictions de tourner", commandsList))
commandsList=[]
}}}
== Voir également ==
* La version originale de cette page en [wiki:/Help/Plugin/Scripting/Python anglais]
----
Retour au [wikitr:/Help/Plugin/Scripting Greffon Scripting] \\
Retour à l'[wikitr:/Plugins Aide des Greffons] \\
Retour à l'[wikitr:/Help Aide Principale]