Changes between Initial Version and Version 1 of Fr:Help/Plugin/Scripting/Python


Ignore:
Timestamp:
2021-08-12T09:11:51+02:00 (3 years ago)
Author:
leni
Comment:

create fr:translation rev17

Legend:

Unmodified
Added
Removed
Modified
  • Fr:Help/Plugin/Scripting/Python

    v1 v1  
     1[[TranslatedPages(revision=17)]]
     2
     3= Greffon -> Scripting -> Python =
     4== Objectif ==
     5D'autres exemples en Python :
     6
     7[[PageOutline(2,Table des Matières)]]
     8
     9
     10== Convertir un chemin qui se raccorde à un carrefour giratoire non fractionné en une bifurcation. ==
     11Convertir 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.
     12
     13{{{#!python
     14from javax.swing import JOptionPane
     15from org.openstreetmap.josm.gui import MainApplication
     16
     17import org.openstreetmap.josm.command as Command
     18import org.openstreetmap.josm.data.osm.Way as Way
     19
     20editLayer = MainApplication.getLayerManager().getEditLayer()
     21if editLayer and editLayer.data:
     22    selected_ways = editLayer.data.getSelectedWays()
     23    print selected_ways
     24
     25    if not(selected_ways) or len(selected_ways)>1:
     26        JOptionPane.showMessageDialog(MainApplication.parent,
     27                                         "Veuillez sélectionner un chemin unique qui se raccorde à un carrefour giratoire")
     28    else:
     29        for way in selected_ways:
     30            if way.get('oneway') in ['yes', '-1']:
     31                JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin a un attribut - sens unique")
     32            else:
     33                node_before = None
     34                node_after = None
     35                common_node = None
     36                common_node_becomes_node_before=None
     37                #print dir(way)
     38                for fln in [way.firstNode(),  way.lastNode()]:
     39                    print 'fln',  fln
     40                    for parentway in fln.getParentWays():
     41                        if parentway.get("junction")=='roundabout':
     42                            for n in parentway.getNodes():
     43                                if common_node:
     44                                    # nous avons trouvé un nœud commun entre le chemin sélectionné et
     45                                    # le chemin du carrefour giratoire dans l'itération précédente
     46                                    node_after = n
     47                                    # nous avons terminé ici
     48                                    break
     49                                if n.getId() == fln.getId():
     50                                    # c'est le nœud que le carrefour giratoire a en commun avec le chemin sélectionné
     51                                    common_node = n
     52                                    if not(node_before):
     53                                        # normalement, nous avons rencontré un nœud du carrefour giratoire
     54                                        # bien avant celui-ci, mais si le nœud commun est le premier nœud
     55                                        # d'un carrefour giratoire non divisé, nous devrons prendre le dernier
     56                                        # nœud du carrefour giratoire à la place
     57                                        node_before = parentway.getNodes()[-2]
     58                                        node_after = parentway.getNodes()[1]
     59                                        break
     60                                    # si ce n'est pas le cas, nous passons par la boucle une fois de plus pour mettre le prochain
     61                                    # nœud dans node_after
     62                                    continue
     63                                node_before = n
     64                        if common_node:
     65                            # si common_node est déjà défini à ce stade, cela signifie qu'il était
     66                            # le premier nœud du chemin sélectionné,
     67                            # il devra donc être remplacé par node_before dans le chemin sélectionné
     68                            common_node_becomes_node_before = True
     69                            adjacent_node_to_split_on = way.getNodes()[1]
     70                            break
     71                        else:
     72                            common_node_becomes_node_before = False
     73                            adjacent_node_to_split_on = way.getNodes()[-1]
     74                if not(common_node) or common_node_becomes_node_before==None:
     75                    JOptionPane.showMessageDialog(MainApplication.parent,
     76                                               "Veuillez sélectionner un chemin qui se raccorde à un carrefour giratoire")
     77                else:
     78                    print common_node.get('name')
     79                    print node_before.get('name')
     80                    print node_after.get('name')
     81
     82                    commandsList = []
     83                    if len(way.getNodes())>2:
     84                        # diviser le dernier segment avant le carrefour giratoire si nécessaire
     85                        commandsList.append(Command.SplitWayCommand.split(
     86                                    way, [adjacent_node_to_split_on], []))
     87                        MainApplication.undoRedo.add(Command.SequenceCommand(
     88                                    "Séparation du chemin sélectionné", commandsList))
     89                        commandsList = []
     90                    # Après la séparation, trouvez le segment qui relie à nouveau le carrefour giratoire
     91                    for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
     92                        if common_node in waypartconnectedtoroundabout.getNodes():
     93                            break
     94                    if len(way.getNodes())==2:
     95                        if common_node == waypartconnectedtoroundabout.firstNode():
     96                            adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
     97                        else:
     98                            adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
     99                    # Il est temps de faire quelque chose
     100                    # de faire une copie du chemin
     101                    modified_way = Way(waypartconnectedtoroundabout)
     102                    # remplacer ses nœuds, de sorte qu'il se transforme en une fourche
     103                    modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
     104                    # ajouter un attribut "oneway"
     105                    modified_way.put('oneway', 'yes')
     106                    # appliquer les modifications
     107                    commandsList.append(Command.ChangeCommand(
     108                                    waypartconnectedtoroundabout, modified_way))
     109                    MainApplication.undoRedo.add(Command.SequenceCommand(
     110                                    "Ajouter un attribut oneway et créer un chemin en forme de fourche", commandsList))
     111                    commandsList = []
     112                    # séparer ce chemin là où il se divise en fourche
     113                    commandsList.append(Command.SplitWayCommand.split(
     114                                    waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
     115                    MainApplication.undoRedo.add(Command.SequenceCommand(
     116                                    "Divisez la fourche en deux chemins", commandsList))
     117                    commandsList = []
     118
     119}}}
     120
     121
     122== Convertir un chemin qui se raccorde à un carrefour giratoire fractionné en une bifurcation ==
     123Ce 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.
     124
     125{{{#!python
     126from javax.swing import JOptionPane
     127from org.openstreetmap.josm.gui import MainApplication
     128
     129import org.openstreetmap.josm.command as Command
     130import org.openstreetmap.josm.data.osm.Way as Way
     131
     132editLayer = MainApplication.getLayerManager().getEditLayer()
     133print '==== Fresh run ===='
     134if editLayer and editLayer.data:
     135    selected_ways = editLayer.data.getSelectedWays()
     136    print selected_ways
     137
     138    if not(selected_ways) or len(selected_ways)>1:
     139        JOptionPane.showMessageDialog(MainApplication.parent, "Veuillez sélectionner un chemin unique qui se connecte à un carrefour giratoire")
     140    else:
     141        for way in selected_ways:
     142            if way.get('oneway') in ['yes', '-1']:
     143                JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin est balisé par un attribut oneway")
     144            elif way.get('junction') in ['roundabout']:
     145                JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin fait partie d'un carrefour giratoire")
     146            else:
     147                node_before = None
     148                node_after = None
     149                common_node = None
     150                common_node_becomes_node_before=None
     151                roundabout_way_before = None
     152                roundabout_way_after = None
     153                for fln in [way.firstNode(),  way.lastNode()]:
     154                    print 'fln',  fln
     155                    for parentway in fln.getParentWays():
     156                        if parentway.get("junction")=='roundabout':
     157                            print parentway.get('name')
     158                            if parentway.isClosed():
     159                                # carrefour giratoire non fractionné
     160                                for n in parentway.getNodes():
     161                                    if common_node:
     162                                        # noeud commun trouvé entre le chemin sélectionné
     163                                        # et le carrefour giratoire dans l'itération précédente
     164                                        node_after = n
     165                                        print node_before.get('name')
     166                                        print node_after.get('name')
     167                                        # nous avons terminé ici
     168                                        break
     169                                    if n.getId() == fln.getId():
     170                                        # c'est le nœud que le carrefour giratoire a en commun avec le chemin sélectionné
     171                                        common_node = n
     172                                        print common_node.get('name')
     173                                        if not(node_before):
     174                                            # normalement, nous avons rencontré un nœud du carrefour giratoire bien
     175                                            # avant celui-ci, mais si le nœud commun est le premier nœud
     176                                            # d'un carrefour giratoire non divisé, nous devrons prendre le dernier
     177                                            # nœud du carrefour giratoire à la place
     178                                            node_before = parentway.getNodes()[-2]
     179                                            node_after = parentway.getNodes()[1]
     180                                            print node_before.get('name')
     181                                            print node_after.get('name')
     182                                            break
     183                                        # si ce n'est pas le cas, nous passons par la boucle une fois de plus pour mettre le prochain
     184                                        # noeud dans node_after
     185                                        continue
     186                                    node_before = n
     187                            else:
     188                                # il s'agit d'un carrefour giratoire fractionné
     189                                if parentway.firstNode().getId() == fln.getId():
     190                                    node_after = parentway.getNodes()[1]
     191                                    roundabout_way_after = parentway
     192                                    print 'node after', node_after.get('name')
     193                                else:
     194                                    node_before = parentway.getNodes()[-2]
     195                                    roundabout_way_before = parentway
     196                                if node_before and node_after:
     197                                    common_node = fln
     198                                    break
     199
     200                            if common_node:
     201                                # si common_node est déjà défini à ce stade, cela signifie que c'était
     202                                # le premier noeud du chemin sélectionné,
     203                                # il devra donc être remplacé par node_before dans le chemin sélectionné
     204                                common_node_becomes_node_before = True
     205                                break
     206                            else:
     207                                common_node_becomes_node_before = False
     208                       
     209                if common_node.getId() == way.firstNode().getId():
     210                    adjacent_node_to_split_on = way.getNodes()[1]
     211                else:
     212                    adjacent_node_to_split_on = way.getNodes()[-1]
     213
     214                if not(common_node) or ((parentway.isClosed() and common_node_becomes_node_before==None)):
     215                    JOptionPane.showMessageDialog(MainApplication.parent, "Please select a way that connects to a roundabout")
     216                else:
     217                    commandsList = []
     218                    if len(way.getNodes())>2:
     219                        # séparer le dernier segment avant le carrefour giratoire si nécessaire
     220                        commandsList.append(Command.SplitWayCommand.split(
     221                                    way, [adjacent_node_to_split_on], []))
     222                        MainApplication.undoRedo.add(Command.SequenceCommand(
     223                                    "Partager le chemin sélectionné", commandsList))
     224                        commandsList = []
     225                    # Après la séparation, trouvez le segment qui rejoint à nouveau le carrefour giratoire
     226                    for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
     227                        if waypartconnectedtoroundabout.get('junction') == 'roundabout':
     228                            continue
     229                        if common_node in waypartconnectedtoroundabout.getNodes():
     230                            break
     231                    if len(way.getNodes())==2:
     232                        if common_node == waypartconnectedtoroundabout.firstNode():
     233                            adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
     234                        else:
     235                            adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
     236                    # Il est temps de faire quelque chose
     237                    # faire une copie du chemin
     238                    modified_way = Way(waypartconnectedtoroundabout)
     239                    # replacer ses nœuds, il devient donc une fourche
     240                    modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
     241                    # ajouter un attribut oneway
     242                    modified_way.put('oneway', 'yes')
     243                    # appliquer les modifications
     244                    commandsList.append(Command.ChangeCommand(
     245                                    waypartconnectedtoroundabout, modified_way))
     246                    MainApplication.undoRedo.add(Command.SequenceCommand(
     247                                    "Ajouter l'attribut oneway et créer un chemin en forme de fourche", commandsList))
     248                    commandsList = []
     249                    # partager ce chemin où il y a une fourche
     250                    commandsList.append(Command.SplitWayCommand.split(
     251                                    waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
     252                    MainApplication.undoRedo.add(Command.SequenceCommand(
     253                                    "Divisez la fourche en deux chemins", commandsList))
     254                    commandsList = []
     255                   
     256                    if roundabout_way_before and roundabout_way_after:
     257                        origway = roundabout_way_before
     258                        roundabout_way_before.addNode(node_after)
     259                        commandsList.append(Command.ChangeCommand(
     260                                        origway,  roundabout_way_before))
     261                        origway = roundabout_way_after
     262                        roundabout_way_after.removeNode(common_node)
     263                        commandsList.append(Command.ChangeCommand(
     264                                        origway,roundabout_way_after))
     265#                        middleway = Way(roundabout_way_after).setNodes(
     266#                                        [node_before, common_node, node_after])
     267#                        commandsList.append(Command.AddCommand(editLayer.data, middleway))
     268#                        MainApplication.undoRedo.add(Command.SequenceCommand(
     269#                                        "Ajouter un chemin sur le carrefour giratoire où la fourche s'attache", commandsList))
     270                        commandsList.append(Command.SplitWayCommand.split(
     271                                        roundabout_way_before, [node_before], []))
     272                        MainApplication.undoRedo.add(Command.SequenceCommand(
     273                                        "decoupe le chemin du giratoire", commandsList))
     274                        commandsList = []
     275
     276}}}
     277
     278
     279== Exporter une collection d'itinéraires vers un fichier GPX Garmin ==
     280Exporter 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) :
     281
     282{{{#!python
     283#!/bin/jython
     284'''
     285RWN2Garmin.py  - Convertisseur de réseaux numérotés en fichiers GPX Garmin
     286Ce code est publié sous la licence GNU General Public License v2 ou ultérieure.
     287
     288La GPL v3 est disponible ici :
     289https://www.gnu.org/licenses/gpl.html
     290
     291Il est livré sans aucune garantie.
     292'''
     293from javax.swing import JOptionPane, JDialog
     294from java.awt.event import ActionListener, ActionEvent
     295from org.openstreetmap.josm import Main
     296import org.openstreetmap.josm.command as Command
     297import org.openstreetmap.josm.data.osm.Node as Node
     298import org.openstreetmap.josm.data.osm.Way as Way
     299import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     300import org.openstreetmap.josm.data.osm.DataSet as DataSet
     301import time
     302
     303f = open('C:/export.gpx', 'w')
     304f.write('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n')
     305f.write('<gpx xmlns="https://www.topografix.com/GPX/1/1" creator="OSM Route Manager" version="1.1" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://wwws.topografix.com/GPX/1/1 https://wwws.topografix.com/GPX/1/1/gpx.xsd">\n')
     306f.write('<!-- All data by OpenStreetMap, licensed under cc-by-sa-2.0 (https://creativecommons.org/licenses/by-sa/2.0/). -->\n')
     307
     308editLayer = Main.getLayerManager().getEditLayer()
     309if editLayer and editLayer.data:
     310    selectedRelations = mv.editLayer.data.getSelectedRelations()
     311
     312    if not(selectedRelations):
     313        JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une relation de collection")
     314    else:
     315        print
     316        for collection in selectedRelations:
     317            print 'COLLECTION:', collection
     318            for member in collection.getMembers():
     319                print 'MEMBER:',member
     320                if member.isNode():
     321                    node = member.getNode()
     322                    coords = node.getCoor()
     323                    lon = coords.getX()
     324                    lat = coords.getY()
     325                    rwn_ref = node.get('rwn_ref')
     326                    f.write('\t<wpt lat="' + str(lat) + '" lon="' + str(lon) + '">\n')
     327                    if rwn_ref:
     328                        f.write('\t\t<name>' + rwn_ref + '</name>\n')
     329                    f.write('\t</wpt>\n')
     330            for member in collection.getMembers():
     331                if member.isRelation():
     332                    routerelation = member.getRelation()
     333                    f.write('\t<trk>\n')
     334                    networkname =  routerelation.get('network:name')
     335                    if not(networkname):
     336                        networkname =  ''
     337                    else:
     338                        networkname += ' '
     339                    note = routerelation.get('note')
     340                    if not(note): note =  ''
     341                    f.write('\t\t<name>' + networkname + note + '</name>\n')
     342                    f.write('\t\t<src>OpenStreetMap.org</src>\n')
     343                    f.write('\t\t<type>foot</type>\n')
     344                    for routerelmember in routerelation.getMembers():
     345                        if routerelmember.isWay():
     346                            f.write('\t\t<trkseg>\n')
     347                            way=routerelmember.getWay()
     348                            for waynode in way.getNodes():
     349                                 coords = waynode.getCoor()
     350                                 lon = coords.getX()
     351                                 lat = coords.getY()
     352                                 f.write('\t\t\t<trkpt lat="' + str(lat) + '" lon="' + str(lon) + '"> </trkpt>\n')
     353
     354                            f.write('\t\t</trkseg>\n')
     355                    f.write('\t</trk>\n')
     356f.write('</gpx>\n')
     357f.close()
     358}}}
     359
     360
     361== Télécharger les éléments parents manquants pour l'élément sélectionné ==
     362
     363{{{#!python
     364#!/bin/jython
     365'''
     366
     367Ce code est publié sous la licence
     368"GNU General Public" v2 ou ultérieure.
     369
     370La GPL v3 est disponible ici :
     371https://www.gnu.org/licenses/gpl.html
     372
     373La GPL v2 est disponible ici :
     374https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
     375
     376Il est livré sans aucune garantie.
     377
     378Ce code illustre comment utiliser Jython pour :
     379* Télécharger tous les référents d'un élément
     380
     381'''
     382from javax.swing import JOptionPane
     383from org.openstreetmap.josm import Main
     384import org.openstreetmap.josm.actions.DownloadReferrersAction as DownloadReferrersAction
     385
     386editLayer = Main.getLayerManager().getEditLayer()
     387if editLayer and editLayer.data:
     388    selectedElements = editLayer.data.getSelected()
     389   
     390    if not(selectedElements):
     391        JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner un élément")
     392    else:
     393        DownloadReferrersAction.downloadReferrers(editLayer, selectedElements)
     394}}}
     395
     396
     397== Télécharger les membres absents de la relation ==
     398
     399{{{
     400#!/bin/jython
     401'''
     402
     403Ce code est publié sous la licence
     404"GNU General Public" v2 ou ultérieure.
     405
     406La GPL v3 est disponible ici :
     407https://www.gnu.org/licenses/gpl.html
     408
     409La GPL v2 est disponible ici :
     410https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
     411
     412Il est livré sans aucune garantie.
     413
     414Ce code illustre comment utiliser Jython pour :
     415* Télécharger tous les membres absents de la relation
     416
     417'''
     418from javax.swing import JOptionPane
     419from org.openstreetmap.josm import Main
     420import org.openstreetmap.josm.data.osm.Node as Node
     421import org.openstreetmap.josm.data.osm.Way as Way
     422import org.openstreetmap.josm.data.osm.Relation as Relation
     423import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     424import org.openstreetmap.josm.data.osm.DataSet as DataSet
     425import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     426import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
     427
     428editLayer = Main.getLayerManager().getEditLayer()
     429if editLayer:
     430    selectedRelations = editLayer.data.getSelectedRelations()
     431   
     432    if not(selectedRelations):
     433        JOptionPane.showMessageDialog(Main.parent, "Please select a relation")
     434    else:
     435        for relation in selectedRelations:
     436            if relation.hasIncompleteMembers():
     437                #print dir(relation)
     438                print dir(DownloadRelationMemberTask)
     439                DownloadRelationMemberTask.run(DownloadRelationMemberTask(relation, relation.getIncompleteMembers(), editLayer ))
     440}}}
     441
     442
     443== Valider une relation de route rcn ==
     444
     445{{{
     446#!/bin/jython
     447'''
     448- Validation d'une relation de route rcn
     449
     450Ce code est publié sous la licence
     451"GNU General Public" v2 ou ultérieure.
     452
     453La GPL v3 est disponible ici :
     454https://www.gnu.org/licenses/gpl.html
     455
     456La GPL v2 est disponible ici :
     457https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
     458
     459Il est livré sans aucune garantie.
     460
     461Ce code illustre comment utiliser Jython pour :
     462* passer en boucle tous les membres d'une relation de route
     463* déterminer si le membre est un noeud, un chemin ou une relation
     464* ajouter/changer les propriétés d'une relation
     465* Supprimer les propriétés d'une relation
     466* Ajouter des membres à une relation
     467* Supprimer des membres d'une relation
     468* trier tous les membres en arrière
     469
     470* Comment définir un élément sélectionné
     471
     472
     473'''
     474from javax.swing import JOptionPane
     475from org.openstreetmap.josm import Main
     476import org.openstreetmap.josm.command as Command
     477import org.openstreetmap.josm.data.osm.Node as Node
     478import org.openstreetmap.josm.data.osm.Way as Way
     479import org.openstreetmap.josm.data.osm.Relation as Relation
     480import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     481import org.openstreetmap.josm.data.osm.DataSet as DataSet
     482import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     483import re
     484
     485commandsList = []
     486reNumberDashNumber = re.compile(r'\d+-\d+')
     487def getMapView():
     488    if Main.main and Main.main.map:
     489        return Main.main.map.mapView
     490    else:
     491        return None
     492
     493mv = getMapView()
     494if mv and mv.editLayer and mv.editLayer.data:
     495    dummy_relation = Relation()
     496    selectedRelations = mv.editLayer.data.getSelectedRelations()
     497
     498    if not(selectedRelations):
     499        JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une relation d'itinéraire")
     500    else:
     501        print
     502        for route in selectedRelations:
     503            newRelation = Relation(route)
     504            relationChanged = False
     505            name = route.get('name')
     506            if name:
     507                if reNumberDashNumber.match(name):
     508                    print 'en supprimant le nom lorsqu'il est de la forme ##-##'
     509                    newRelation.remove('name')
     510                    relationChanged = True
     511            else:
     512                name = ''
     513            ref = route.get('ref')
     514            if ref:
     515                if reNumberDashNumber.match(ref):
     516                    print 'en supprimant ref lorsqu'elle est de la forme ##-##'
     517                    newRelation.remove('ref')
     518                    relationChanged = True
     519            else:
     520                ref = ''
     521            if relationChanged:
     522                commandsList.append(Command.ChangeCommand(route, newRelation))
     523               
     524                Main.main.undoRedo.add(Command.SequenceCommand("Removing name and/or ref " + name + '/' + ref, commandsList))
     525                commandsList = []
     526
     527            rcn_refs = []; route_relation_names = []; memberslist = []
     528            endnodes = []; prev_endnodes = []
     529            continuous_forward = True; continuous_backward = True
     530            prev_role = None; prev_endnodes_before_forward = None; last_endnodes_before_backward = None
     531            for member in route.getMembers():
     532                if member.isWay():
     533                    role = member.getRole()
     534                    memberslist.append(member)
     535                    way = member.getWay()
     536                    #JOptionPane.showMessageDialog(Main.parent, 'way is selected')
     537                    endnodes = [way.getNode(0), way.getNode(way.nodesCount-1)]
     538                    notfoundyet = True
     539                    for endnode in endnodes:
     540                        # inventorizing of rcn_ref on end nodes
     541                        rcn_ref = endnode.get('rcn_ref')
     542                        if rcn_ref:
     543                            rcn_refs.append(int(rcn_ref))
     544                            for referrer in endnode.getReferrers():
     545                                if referrer.getType() is dummy_relation.getType():
     546                                    if referrer.get('type')=='network' and referrer.get('network')=='rcn':
     547                                        relname=referrer.get('name')
     548                                        if relname:
     549                                            route_relation_names.append(relname)
     550                                       
     551                                    elif referrer.get('type')=='collection':
     552                                        route_relation_names.append('Node not assigned to network yet')
     553                        # checking for continuity on ways
     554                        if notfoundyet:
     555                            if role:
     556                                if prev_role:
     557                                    if role=='forward' and prev_role=='forward' and endnode in prev_endnodes:
     558                                        notfoundyet = False
     559                                    elif role=='forward' and prev_role=='backward' and endnode in last_endnodes_before_backward:
     560                                        notfoundyet = False
     561                                    elif role=='backward' and prev_role=='forward' and endnode in prev_endnodes:
     562                                        notfoundyet = False
     563                                    elif role=='backward' and prev_role=='backward' and endnode in prev_endnodes:
     564                                        notfoundyet = False
     565                                else:
     566                                    if role=='forward' and endnode in prev_endnodes:
     567                                        notfoundyet = False
     568                                    elif role=='backward' and endnode in prev_endnodes:
     569                                        notfoundyet = False
     570                            else:
     571                                if prev_role:
     572                                    if prev_role=='forward' and endnode in prev_endnodes:
     573                                        notfoundyet = False
     574                                    elif prev_role=='backward' and endnode in last_endnodes_before_backward:
     575                                        notfoundyet = False
     576                                else:
     577                                    if endnode in prev_endnodes:
     578                                        notfoundyet = False
     579                    # Analysis of continuity of ways
     580                    if prev_endnodes and notfoundyet:
     581                        if role:
     582                            if role == 'forward':
     583                                continuous_forward = False
     584                            elif role == 'backward':
     585                                continuous_backward = False
     586                        else:
     587                            continuous_forward = False
     588                            continuous_backward = False
     589                    if role=='forward':
     590                        if not(prev_endnodes_before_forward):
     591                            prev_endnodes_before_forward  = prev_endnodes
     592                    elif prev_role=='forward' and role=='backward':
     593                        if not(last_endnodes_before_backward):
     594                            last_endnodes_before_backward = prev_endnodes
     595                    elif not(role) and prev_role=='backward':
     596                        prev_endnodes_before_forward = None
     597                    prev_role = role
     598                    prev_endnodes = endnodes
     599            # Drawing conclusions about continuity of ways
     600            if continuous_forward:
     601                print 'Itinéraire continu dans la direction vers devant'
     602            else:
     603                print 'Itinéraire PAS CONTINU dans la direction vers devant'
     604            if continuous_backward:
     605                print 'Itinéraire continu dans la direction vers arrière'
     606            else:
     607                print 'Itinéraire PAS CONTINU dans la direction vers arrière'
     608
     609            # Drawing conclusions about rcn_refs
     610            print rcn_refs
     611            if len(rcn_refs) > 1:
     612                newRelation = Relation(route)
     613                relationChanged = False
     614
     615                if rcn_refs[0] > rcn_refs[1]:
     616                    rcn_refs.sort()
     617                    print 'Inversion de l'ordre des membres'
     618                    for member in reversed(memberslist):
     619                        newRelation.addMember( newRelation.getMembersCount(), member)
     620                        newRelation.removeMember (0)
     621                    commandsList.append(Command.ChangeCommand(route, newRelation))
     622                    Main.main.undoRedo.add(Command.SequenceCommand("Flipping order of members", commandsList))
     623                    commandsList = []
     624                note = route.get('note')
     625                newNote = str(rcn_refs[0]).zfill(2) + '-' + str(rcn_refs[1]).zfill(2)
     626                if not(note) or note != newNote:
     627                    if not(note): note = 'nothing'
     628                    newRelation.put('note', newNote)
     629                    relationChanged = True
     630                    commandsList.append(Command.ChangeCommand(route, newRelation))
     631               
     632                    Main.main.undoRedo.add(Command.SequenceCommand("Changing note from " + note + ' to ' + newNote, commandsList))
     633                    commandsList = []
     634
     635                if len(route_relation_names) > 1 and route_relation_names[0] != route_relation_names[1]:
     636                    print
     637                    print 'Il s'agit probablement d'une CONNEXION à un autre réseau'
     638                    print route_relation_names
     639            else:
     640                print 'moins de 2 noeuds terminaux avec rcn_ref trouvés'
     641}}}
     642
     643[wiki:/Help/Plugin/Scripting/Python/RCN_Route_Validator]
     644
     645
     646== Suppression des chemins supplémentaires résultant d'opérations Potlatch  ==
     647Suppression des chemins supplémentaires résultant des opérations de division des chemins de Potlatch dans le cadre des relations d'interdiction de tourner.
     648
     649{{{#!python
     650#!/bin/jython
     651
     652'''
     653RepairTurns.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
     654
     655Ce code est publié sous la licence
     656"GNU General Public" v2 ou ultérieure.
     657
     658La GPL v3 est disponible ici :
     659https://www.gnu.org/licenses/gpl.html
     660
     661Il est livré sans aucune garantie.
     662
     663Ce 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.
     664
     665Ne fonctionne que pour les interdiction de tourner avec un noeud via
     666
     667e.g. Original      : from: Way1, via: Node, to:Way2
     668     Split         : from: Way1a, from: Way1b, via: Node, to: Way2
     669     After running : from: Way1b, via: Node, to: Way2
     670
     671Ce code illustre comment utiliser Jython pour :
     672* traiter les éléments sélectionnés
     673* télécharger les primitives manquantes dans le même thread (blocage)
     674* traiter, valider et supprimer des membres de relations
     675
     676'''
     677from javax.swing import JOptionPane
     678from org.openstreetmap.josm import Main
     679import org.openstreetmap.josm.data.osm.Node as Node
     680import org.openstreetmap.josm.data.osm.Way as Way
     681import org.openstreetmap.josm.data.osm.Relation as Relation
     682import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     683import org.openstreetmap.josm.data.osm.DataSet as DataSet
     684import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     685import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
     686import org.openstreetmap.josm.io.MultiFetchServerObjectReader as MultiFetchServerObjectReader
     687import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor as PleaseWaitProgressMonitor
     688import org.openstreetmap.josm.command as Command
     689
     690class RestrictionError(Exception):
     691    pass
     692
     693def getMembers (restriction):
     694    memberlist = dict()
     695    for member in restriction.getMembers():
     696        memberRole = member.getRole()
     697        if memberRole == "via":
     698            if member.isNode() and not "via" in memberlist:
     699                memberlist[memberRole] = [member]
     700            else:
     701                raise RestrictionError, "Plus d'un avec rôle via ou avec via mais ce n'est pas un nœud"
     702        elif memberRole in ("from", "to"):
     703            if member.isWay():
     704                try:
     705                    memberlist[memberRole].append (member)
     706                except KeyError:
     707                    memberlist[memberRole] = [member]
     708            else:
     709                raise RestrictionError, "avec le rôle From ou to mais n'est pas un chemin"
     710        else:
     711            raise RestrictionError, "Rôle inconnu " + memberRole
     712
     713    if len(memberlist.keys())<3:
     714        raise RestrictionError, "Certains rôles manquent : Seulement " + ",".join (memberlist.keys()) + " found"
     715    return memberlist
     716
     717def downloadPrimitives (primitives, editlayer):
     718    """
     719        Télécharger une liste de primitives depuis le serveur, et les fusionner dans editlayer.
     720Blocking.
     721    """
     722    monitor = PleaseWaitProgressMonitor()
     723    monitor.showForegroundDialog()   
     724
     725    print "Téléchargement"
     726    try:
     727        objectReader = MultiFetchServerObjectReader().append (primitives)
     728        dataSet = objectReader.parseOsm (monitor)
     729        editlayer.mergeFrom (dataSet)
     730        editlayer.onPostDownloadFromServer()
     731        if (not objectReader.getMissingPrimitives().isEmpty()) :
     732            raise RestrictionError, "Impossible de télécharger les primitives manquantes"
     733        print "Téléchargement terminé"
     734    finally:
     735        monitor.close()
     736
     737def checkIfConnected (node, way, reverse):
     738    """
     739        Return (connecté, prochain nœud à comparer (c'est-à-dire l'autre extrémité du nœud) si vrai)
     740    """
     741    if (way.isOneway() != 0 and reverse):
     742        return node == way.lastNode(True), way.firstNode(True) # True: auto process case whan isOneway == -1
     743    if (way.isOneway() != 0):     # pas d'inversion
     744        return node == way.firstNode(True), way.lastNode(True)
     745    if node == way.firstNode():
     746        return True, way.lastNode()
     747    if node == way.lastNode():
     748        return True, way.firstNode()
     749    return False, node   
     750
     751
     752def repairrestriction (relation, memberlist, editLayer):
     753    """
     754        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
     755    """
     756    incompleteMembers = relation.getIncompleteMembers()
     757    if incompleteMembers:
     758          downloadPrimitives (incompleteMembers, editLayer);       
     759
     760    fromRemovalList = []; toRemovalList = []
     761   
     762    if len (memberlist["from"]) >= 1:
     763        currnode = memberlist["via"][0].getNode()
     764        firstMember = True
     765        failed = False;
     766        # trace "from" des membres pour confirmer s'ils sont séparés d'un seul chemin
     767        for member in reversed(memberlist['from']):
     768            connected, currnode = checkIfConnected (currnode, member.getWay(), True)
     769            if not connected:
     770                if not firstMember:
     771                    raise RestrictionError, "des chemins non continus du noeud via"
     772                failed = True
     773                break
     774            if not firstMember:
     775                fromRemovalList.append (member)
     776            else:
     777                firstMember = False
     778
     779        if failed: # Deuxième tentative en cas d'inversion de la séquence lors du fractionnement
     780            currnode = memberlist["via"][0].getNode()
     781            for member in memberlist['from']:
     782                connected, currnode = checkIfConnected (currnode, member.getWay(), True)
     783                if not connected:
     784                    raise RestrictionError, "des chemins non continus du noeud via"
     785                if not firstMember:
     786                    fromRemovalList.append (member)
     787                else:
     788                    firstMember = False
     789                                                                       
     790    if len (memberlist["to"]) >= 1:
     791        currnode = memberlist["via"][0].getNode()
     792        firstMember = True
     793        failed = False
     794        # trace les membres " to " pour confirmer s'ils ont été séparés d'un chemin
     795        for member in memberlist['to']:
     796            connected, currnode = checkIfConnected (currnode, member.getWay(), False)
     797            if not connected:
     798                if not firstMember:
     799                    raise RestrictionError, "chemins to non continus avec le noeud via"
     800                failed = True
     801                break
     802            if not firstMember:
     803                toRemovalList.append (member)
     804            else:
     805                firstMember = False
     806
     807        if failed: # Deuxième tentative en cas d'inversion de la séquence lors du fractionnement
     808            currnode = memberlist["via"][0].getNode()
     809            for member in reversed(memberlist['to']):
     810                connected, currnode = checkIfConnected (currnode, member.getWay(), False)
     811                if not connected:
     812                    raise RestrictionError, "chemins to non continus avec le noeud via"
     813                if not firstMember:
     814                    toRemovalList.append (member)
     815                else:
     816                    firstMember = False         
     817                         
     818    # pour supprimer les chemins dans fromRemovalList, toRemovalList
     819    newRelation = Relation(relation)
     820    waysToRemove = set()
     821    for removalList in [fromRemovalList, toRemovalList]:
     822        waysToRemove |= set ([m.getWay() for m in removalList])
     823    newRelation.removeMembersFor (waysToRemove)
     824    print "Supprimer le(s) chemin(s) identifiant : " + ",".join ([str(w.getId()) for w in waysToRemove])
     825    return Command.ChangeCommand (relation, newRelation)   
     826   
     827   
     828validrestrictiontypes = ('only_straight_on', 'only_right_turn', 'only_left_turn', 'no_right_turn', 'no_left_turn', 'no_straight_on', 'no_u_turn')
     829editLayer = Main.getLayerManager().getEditLayer()
     830if editLayer and editLayer.data:
     831    selectedRelations = editLayer.data.getSelectedRelations()
     832   
     833    if not(selectedRelations):
     834        JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une ou plusieurs relations")
     835    else:
     836        commandsList = []
     837        for relation in selectedRelations:
     838            if relation.get('type') == "restriction" and relation.get('restriction') in validrestrictiontypes:
     839                try:
     840                    memberlist = getMembers (relation)
     841                    if (len (memberlist["from"])) > 1 or (len (memberlist["to"])) > 1 :
     842                        # Tentative de réparation
     843                        print "Tentative de réparation",
     844                        print "relation id: " + str(relation.getId())
     845                        command = repairrestriction (relation, memberlist, mv.editLayer)
     846                        print "Succès"                         
     847                        commandsList.append (command)
     848                except RestrictionError, e:
     849                    print str(e), "; relation id: "+ str(relation.getId())
     850               
     851       
     852        Main.main.undoRedo.add(Command.SequenceCommand("Réparation des interdictions de tourner", commandsList))
     853        commandsList=[]
     854}}}
     855
     856
     857== Voir également ==
     858* La version originale de cette page en [wiki:/Help/Plugin/Scripting/Python anglais]
     859
     860
     861----
     862Retour au [wikitr:/Help/Plugin/Scripting Greffon Scripting] \\
     863Retour à l'[wikitr:/Plugins Aide des Greffons] \\
     864Retour à l'[wikitr:/Help Aide Principale][[TranslatedPages(revision=17)]]
     865
     866= Greffon -> Scripting -> Python =
     867== Objectif ==
     868D'autres exemples en Python :
     869
     870[[PageOutline(2,Table des Matières)]]
     871
     872
     873== Convertir un chemin qui se raccorde à un carrefour giratoire non fractionné en une bifurcation. ==
     874Convertir 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.
     875
     876{{{#!python
     877from javax.swing import JOptionPane
     878from org.openstreetmap.josm.gui import MainApplication
     879
     880import org.openstreetmap.josm.command as Command
     881import org.openstreetmap.josm.data.osm.Way as Way
     882
     883editLayer = MainApplication.getLayerManager().getEditLayer()
     884if editLayer and editLayer.data:
     885    selected_ways = editLayer.data.getSelectedWays()
     886    print selected_ways
     887
     888    if not(selected_ways) or len(selected_ways)>1:
     889        JOptionPane.showMessageDialog(MainApplication.parent,
     890                                         "Veuillez sélectionner un chemin unique qui se raccorde à un carrefour giratoire")
     891    else:
     892        for way in selected_ways:
     893            if way.get('oneway') in ['yes', '-1']:
     894                JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin a un attribut - sens unique")
     895            else:
     896                node_before = None
     897                node_after = None
     898                common_node = None
     899                common_node_becomes_node_before=None
     900                #print dir(way)
     901                for fln in [way.firstNode(),  way.lastNode()]:
     902                    print 'fln',  fln
     903                    for parentway in fln.getParentWays():
     904                        if parentway.get("junction")=='roundabout':
     905                            for n in parentway.getNodes():
     906                                if common_node:
     907                                    # nous avons trouvé un nœud commun entre le chemin sélectionné et
     908                                    # le chemin du carrefour giratoire dans l'itération précédente
     909                                    node_after = n
     910                                    # nous avons terminé ici
     911                                    break
     912                                if n.getId() == fln.getId():
     913                                    # c'est le nœud que le carrefour giratoire a en commun avec le chemin sélectionné
     914                                    common_node = n
     915                                    if not(node_before):
     916                                        # normalement, nous avons rencontré un nœud du carrefour giratoire
     917                                        # bien avant celui-ci, mais si le nœud commun est le premier nœud
     918                                        # d'un carrefour giratoire non divisé, nous devrons prendre le dernier
     919                                        # nœud du carrefour giratoire à la place
     920                                        node_before = parentway.getNodes()[-2]
     921                                        node_after = parentway.getNodes()[1]
     922                                        break
     923                                    # si ce n'est pas le cas, nous passons par la boucle une fois de plus pour mettre le prochain
     924                                    # nœud dans node_after
     925                                    continue
     926                                node_before = n
     927                        if common_node:
     928                            # si common_node est déjà défini à ce stade, cela signifie qu'il était
     929                            # le premier nœud du chemin sélectionné,
     930                            # il devra donc être remplacé par node_before dans le chemin sélectionné
     931                            common_node_becomes_node_before = True
     932                            adjacent_node_to_split_on = way.getNodes()[1]
     933                            break
     934                        else:
     935                            common_node_becomes_node_before = False
     936                            adjacent_node_to_split_on = way.getNodes()[-1]
     937                if not(common_node) or common_node_becomes_node_before==None:
     938                    JOptionPane.showMessageDialog(MainApplication.parent,
     939                                               "Veuillez sélectionner un chemin qui se raccorde à un carrefour giratoire")
     940                else:
     941                    print common_node.get('name')
     942                    print node_before.get('name')
     943                    print node_after.get('name')
     944
     945                    commandsList = []
     946                    if len(way.getNodes())>2:
     947                        # diviser le dernier segment avant le carrefour giratoire si nécessaire
     948                        commandsList.append(Command.SplitWayCommand.split(
     949                                    way, [adjacent_node_to_split_on], []))
     950                        MainApplication.undoRedo.add(Command.SequenceCommand(
     951                                    "Séparation du chemin sélectionné", commandsList))
     952                        commandsList = []
     953                    # Après la séparation, trouvez le segment qui relie à nouveau le carrefour giratoire
     954                    for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
     955                        if common_node in waypartconnectedtoroundabout.getNodes():
     956                            break
     957                    if len(way.getNodes())==2:
     958                        if common_node == waypartconnectedtoroundabout.firstNode():
     959                            adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
     960                        else:
     961                            adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
     962                    # Il est temps de faire quelque chose
     963                    # de faire une copie du chemin
     964                    modified_way = Way(waypartconnectedtoroundabout)
     965                    # remplacer ses nœuds, de sorte qu'il se transforme en une fourche
     966                    modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
     967                    # ajouter un attribut "oneway"
     968                    modified_way.put('oneway', 'yes')
     969                    # appliquer les modifications
     970                    commandsList.append(Command.ChangeCommand(
     971                                    waypartconnectedtoroundabout, modified_way))
     972                    MainApplication.undoRedo.add(Command.SequenceCommand(
     973                                    "Ajouter un attribut oneway et créer un chemin en forme de fourche", commandsList))
     974                    commandsList = []
     975                    # séparer ce chemin là où il se divise en fourche
     976                    commandsList.append(Command.SplitWayCommand.split(
     977                                    waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
     978                    MainApplication.undoRedo.add(Command.SequenceCommand(
     979                                    "Divisez la fourche en deux chemins", commandsList))
     980                    commandsList = []
     981
     982}}}
     983
     984
     985== Convertir un chemin qui se raccorde à un carrefour giratoire fractionné en une bifurcation ==
     986Ce 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.
     987
     988{{{#!python
     989from javax.swing import JOptionPane
     990from org.openstreetmap.josm.gui import MainApplication
     991
     992import org.openstreetmap.josm.command as Command
     993import org.openstreetmap.josm.data.osm.Way as Way
     994
     995editLayer = MainApplication.getLayerManager().getEditLayer()
     996print '==== Fresh run ===='
     997if editLayer and editLayer.data:
     998    selected_ways = editLayer.data.getSelectedWays()
     999    print selected_ways
     1000
     1001    if not(selected_ways) or len(selected_ways)>1:
     1002        JOptionPane.showMessageDialog(MainApplication.parent, "Veuillez sélectionner un chemin unique qui se connecte à un carrefour giratoire")
     1003    else:
     1004        for way in selected_ways:
     1005            if way.get('oneway') in ['yes', '-1']:
     1006                JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin est balisé par un attribut oneway")
     1007            elif way.get('junction') in ['roundabout']:
     1008                JOptionPane.showMessageDialog(MainApplication.parent, "Ce chemin fait partie d'un carrefour giratoire")
     1009            else:
     1010                node_before = None
     1011                node_after = None
     1012                common_node = None
     1013                common_node_becomes_node_before=None
     1014                roundabout_way_before = None
     1015                roundabout_way_after = None
     1016                for fln in [way.firstNode(),  way.lastNode()]:
     1017                    print 'fln',  fln
     1018                    for parentway in fln.getParentWays():
     1019                        if parentway.get("junction")=='roundabout':
     1020                            print parentway.get('name')
     1021                            if parentway.isClosed():
     1022                                # carrefour giratoire non fractionné
     1023                                for n in parentway.getNodes():
     1024                                    if common_node:
     1025                                        # noeud commun trouvé entre le chemin sélectionné
     1026                                        # et le carrefour giratoire dans l'itération précédente
     1027                                        node_after = n
     1028                                        print node_before.get('name')
     1029                                        print node_after.get('name')
     1030                                        # nous avons terminé ici
     1031                                        break
     1032                                    if n.getId() == fln.getId():
     1033                                        # c'est le nœud que le carrefour giratoire a en commun avec le chemin sélectionné
     1034                                        common_node = n
     1035                                        print common_node.get('name')
     1036                                        if not(node_before):
     1037                                            # normalement, nous avons rencontré un nœud du carrefour giratoire bien
     1038                                            # avant celui-ci, mais si le nœud commun est le premier nœud
     1039                                            # d'un carrefour giratoire non divisé, nous devrons prendre le dernier
     1040                                            # nœud du carrefour giratoire à la place
     1041                                            node_before = parentway.getNodes()[-2]
     1042                                            node_after = parentway.getNodes()[1]
     1043                                            print node_before.get('name')
     1044                                            print node_after.get('name')
     1045                                            break
     1046                                        # si ce n'est pas le cas, nous passons par la boucle une fois de plus pour mettre le prochain
     1047                                        # noeud dans node_after
     1048                                        continue
     1049                                    node_before = n
     1050                            else:
     1051                                # il s'agit d'un carrefour giratoire fractionné
     1052                                if parentway.firstNode().getId() == fln.getId():
     1053                                    node_after = parentway.getNodes()[1]
     1054                                    roundabout_way_after = parentway
     1055                                    print 'node after', node_after.get('name')
     1056                                else:
     1057                                    node_before = parentway.getNodes()[-2]
     1058                                    roundabout_way_before = parentway
     1059                                if node_before and node_after:
     1060                                    common_node = fln
     1061                                    break
     1062
     1063                            if common_node:
     1064                                # si common_node est déjà défini à ce stade, cela signifie que c'était
     1065                                # le premier noeud du chemin sélectionné,
     1066                                # il devra donc être remplacé par node_before dans le chemin sélectionné
     1067                                common_node_becomes_node_before = True
     1068                                break
     1069                            else:
     1070                                common_node_becomes_node_before = False
     1071                       
     1072                if common_node.getId() == way.firstNode().getId():
     1073                    adjacent_node_to_split_on = way.getNodes()[1]
     1074                else:
     1075                    adjacent_node_to_split_on = way.getNodes()[-1]
     1076
     1077                if not(common_node) or ((parentway.isClosed() and common_node_becomes_node_before==None)):
     1078                    JOptionPane.showMessageDialog(MainApplication.parent, "Please select a way that connects to a roundabout")
     1079                else:
     1080                    commandsList = []
     1081                    if len(way.getNodes())>2:
     1082                        # séparer le dernier segment avant le carrefour giratoire si nécessaire
     1083                        commandsList.append(Command.SplitWayCommand.split(
     1084                                    way, [adjacent_node_to_split_on], []))
     1085                        MainApplication.undoRedo.add(Command.SequenceCommand(
     1086                                    "Partager le chemin sélectionné", commandsList))
     1087                        commandsList = []
     1088                    # Après la séparation, trouvez le segment qui rejoint à nouveau le carrefour giratoire
     1089                    for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
     1090                        if waypartconnectedtoroundabout.get('junction') == 'roundabout':
     1091                            continue
     1092                        if common_node in waypartconnectedtoroundabout.getNodes():
     1093                            break
     1094                    if len(way.getNodes())==2:
     1095                        if common_node == waypartconnectedtoroundabout.firstNode():
     1096                            adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
     1097                        else:
     1098                            adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
     1099                    # Il est temps de faire quelque chose
     1100                    # faire une copie du chemin
     1101                    modified_way = Way(waypartconnectedtoroundabout)
     1102                    # replacer ses nœuds, il devient donc une fourche
     1103                    modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
     1104                    # ajouter un attribut oneway
     1105                    modified_way.put('oneway', 'yes')
     1106                    # appliquer les modifications
     1107                    commandsList.append(Command.ChangeCommand(
     1108                                    waypartconnectedtoroundabout, modified_way))
     1109                    MainApplication.undoRedo.add(Command.SequenceCommand(
     1110                                    "Ajouter l'attribut oneway et créer un chemin en forme de fourche", commandsList))
     1111                    commandsList = []
     1112                    # partager ce chemin où il y a une fourche
     1113                    commandsList.append(Command.SplitWayCommand.split(
     1114                                    waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
     1115                    MainApplication.undoRedo.add(Command.SequenceCommand(
     1116                                    "Divisez la fourche en deux chemins", commandsList))
     1117                    commandsList = []
     1118                   
     1119                    if roundabout_way_before and roundabout_way_after:
     1120                        origway = roundabout_way_before
     1121                        roundabout_way_before.addNode(node_after)
     1122                        commandsList.append(Command.ChangeCommand(
     1123                                        origway,  roundabout_way_before))
     1124                        origway = roundabout_way_after
     1125                        roundabout_way_after.removeNode(common_node)
     1126                        commandsList.append(Command.ChangeCommand(
     1127                                        origway,roundabout_way_after))
     1128#                        middleway = Way(roundabout_way_after).setNodes(
     1129#                                        [node_before, common_node, node_after])
     1130#                        commandsList.append(Command.AddCommand(editLayer.data, middleway))
     1131#                        MainApplication.undoRedo.add(Command.SequenceCommand(
     1132#                                        "Ajouter un chemin sur le carrefour giratoire où la fourche s'attache", commandsList))
     1133                        commandsList.append(Command.SplitWayCommand.split(
     1134                                        roundabout_way_before, [node_before], []))
     1135                        MainApplication.undoRedo.add(Command.SequenceCommand(
     1136                                        "decoupe le chemin du giratoire", commandsList))
     1137                        commandsList = []
     1138
     1139}}}
     1140
     1141
     1142== Exporter une collection d'itinéraires vers un fichier GPX Garmin ==
     1143Exporter 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) :
     1144
     1145{{{#!python
     1146#!/bin/jython
     1147'''
     1148RWN2Garmin.py  - Convertisseur de réseaux numérotés en fichiers GPX Garmin
     1149Ce code est publié sous la licence GNU General Public License v2 ou ultérieure.
     1150
     1151La GPL v3 est disponible ici :
     1152https://www.gnu.org/licenses/gpl.html
     1153
     1154Il est livré sans aucune garantie.
     1155'''
     1156from javax.swing import JOptionPane, JDialog
     1157from java.awt.event import ActionListener, ActionEvent
     1158from org.openstreetmap.josm import Main
     1159import org.openstreetmap.josm.command as Command
     1160import org.openstreetmap.josm.data.osm.Node as Node
     1161import org.openstreetmap.josm.data.osm.Way as Way
     1162import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     1163import org.openstreetmap.josm.data.osm.DataSet as DataSet
     1164import time
     1165
     1166f = open('C:/export.gpx', 'w')
     1167f.write('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n')
     1168f.write('<gpx xmlns="https://www.topografix.com/GPX/1/1" creator="OSM Route Manager" version="1.1" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://wwws.topografix.com/GPX/1/1 https://wwws.topografix.com/GPX/1/1/gpx.xsd">\n')
     1169f.write('<!-- All data by OpenStreetMap, licensed under cc-by-sa-2.0 (https://creativecommons.org/licenses/by-sa/2.0/). -->\n')
     1170
     1171editLayer = Main.getLayerManager().getEditLayer()
     1172if editLayer and editLayer.data:
     1173    selectedRelations = mv.editLayer.data.getSelectedRelations()
     1174
     1175    if not(selectedRelations):
     1176        JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une relation de collection")
     1177    else:
     1178        print
     1179        for collection in selectedRelations:
     1180            print 'COLLECTION:', collection
     1181            for member in collection.getMembers():
     1182                print 'MEMBER:',member
     1183                if member.isNode():
     1184                    node = member.getNode()
     1185                    coords = node.getCoor()
     1186                    lon = coords.getX()
     1187                    lat = coords.getY()
     1188                    rwn_ref = node.get('rwn_ref')
     1189                    f.write('\t<wpt lat="' + str(lat) + '" lon="' + str(lon) + '">\n')
     1190                    if rwn_ref:
     1191                        f.write('\t\t<name>' + rwn_ref + '</name>\n')
     1192                    f.write('\t</wpt>\n')
     1193            for member in collection.getMembers():
     1194                if member.isRelation():
     1195                    routerelation = member.getRelation()
     1196                    f.write('\t<trk>\n')
     1197                    networkname =  routerelation.get('network:name')
     1198                    if not(networkname):
     1199                        networkname =  ''
     1200                    else:
     1201                        networkname += ' '
     1202                    note = routerelation.get('note')
     1203                    if not(note): note =  ''
     1204                    f.write('\t\t<name>' + networkname + note + '</name>\n')
     1205                    f.write('\t\t<src>OpenStreetMap.org</src>\n')
     1206                    f.write('\t\t<type>foot</type>\n')
     1207                    for routerelmember in routerelation.getMembers():
     1208                        if routerelmember.isWay():
     1209                            f.write('\t\t<trkseg>\n')
     1210                            way=routerelmember.getWay()
     1211                            for waynode in way.getNodes():
     1212                                 coords = waynode.getCoor()
     1213                                 lon = coords.getX()
     1214                                 lat = coords.getY()
     1215                                 f.write('\t\t\t<trkpt lat="' + str(lat) + '" lon="' + str(lon) + '"> </trkpt>\n')
     1216
     1217                            f.write('\t\t</trkseg>\n')
     1218                    f.write('\t</trk>\n')
     1219f.write('</gpx>\n')
     1220f.close()
     1221}}}
     1222
     1223
     1224== Télécharger les éléments parents manquants pour l'élément sélectionné ==
     1225
     1226{{{#!python
     1227#!/bin/jython
     1228'''
     1229
     1230Ce code est publié sous la licence
     1231"GNU General Public" v2 ou ultérieure.
     1232
     1233La GPL v3 est disponible ici :
     1234https://www.gnu.org/licenses/gpl.html
     1235
     1236La GPL v2 est disponible ici :
     1237https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
     1238
     1239Il est livré sans aucune garantie.
     1240
     1241Ce code illustre comment utiliser Jython pour :
     1242* Télécharger tous les référents d'un élément
     1243
     1244'''
     1245from javax.swing import JOptionPane
     1246from org.openstreetmap.josm import Main
     1247import org.openstreetmap.josm.actions.DownloadReferrersAction as DownloadReferrersAction
     1248
     1249editLayer = Main.getLayerManager().getEditLayer()
     1250if editLayer and editLayer.data:
     1251    selectedElements = editLayer.data.getSelected()
     1252   
     1253    if not(selectedElements):
     1254        JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner un élément")
     1255    else:
     1256        DownloadReferrersAction.downloadReferrers(editLayer, selectedElements)
     1257}}}
     1258
     1259
     1260== Télécharger les membres absents de la relation ==
     1261
     1262{{{
     1263#!/bin/jython
     1264'''
     1265
     1266Ce code est publié sous la licence
     1267"GNU General Public" v2 ou ultérieure.
     1268
     1269La GPL v3 est disponible ici :
     1270https://www.gnu.org/licenses/gpl.html
     1271
     1272La GPL v2 est disponible ici :
     1273https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
     1274
     1275Il est livré sans aucune garantie.
     1276
     1277Ce code illustre comment utiliser Jython pour :
     1278* Télécharger tous les membres absents de la relation
     1279
     1280'''
     1281from javax.swing import JOptionPane
     1282from org.openstreetmap.josm import Main
     1283import org.openstreetmap.josm.data.osm.Node as Node
     1284import org.openstreetmap.josm.data.osm.Way as Way
     1285import org.openstreetmap.josm.data.osm.Relation as Relation
     1286import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     1287import org.openstreetmap.josm.data.osm.DataSet as DataSet
     1288import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     1289import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
     1290
     1291editLayer = Main.getLayerManager().getEditLayer()
     1292if editLayer:
     1293    selectedRelations = editLayer.data.getSelectedRelations()
     1294   
     1295    if not(selectedRelations):
     1296        JOptionPane.showMessageDialog(Main.parent, "Please select a relation")
     1297    else:
     1298        for relation in selectedRelations:
     1299            if relation.hasIncompleteMembers():
     1300                #print dir(relation)
     1301                print dir(DownloadRelationMemberTask)
     1302                DownloadRelationMemberTask.run(DownloadRelationMemberTask(relation, relation.getIncompleteMembers(), editLayer ))
     1303}}}
     1304
     1305
     1306== Valider une relation de route rcn ==
     1307
     1308{{{
     1309#!/bin/jython
     1310'''
     1311- Validation d'une relation de route rcn
     1312
     1313Ce code est publié sous la licence
     1314"GNU General Public" v2 ou ultérieure.
     1315
     1316La GPL v3 est disponible ici :
     1317https://www.gnu.org/licenses/gpl.html
     1318
     1319La GPL v2 est disponible ici :
     1320https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
     1321
     1322Il est livré sans aucune garantie.
     1323
     1324Ce code illustre comment utiliser Jython pour :
     1325* passer en boucle tous les membres d'une relation de route
     1326* déterminer si le membre est un noeud, un chemin ou une relation
     1327* ajouter/changer les propriétés d'une relation
     1328* Supprimer les propriétés d'une relation
     1329* Ajouter des membres à une relation
     1330* Supprimer des membres d'une relation
     1331* trier tous les membres en arrière
     1332
     1333* Comment définir un élément sélectionné
     1334
     1335
     1336'''
     1337from javax.swing import JOptionPane
     1338from org.openstreetmap.josm import Main
     1339import org.openstreetmap.josm.command as Command
     1340import org.openstreetmap.josm.data.osm.Node as Node
     1341import org.openstreetmap.josm.data.osm.Way as Way
     1342import org.openstreetmap.josm.data.osm.Relation as Relation
     1343import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     1344import org.openstreetmap.josm.data.osm.DataSet as DataSet
     1345import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     1346import re
     1347
     1348commandsList = []
     1349reNumberDashNumber = re.compile(r'\d+-\d+')
     1350def getMapView():
     1351    if Main.main and Main.main.map:
     1352        return Main.main.map.mapView
     1353    else:
     1354        return None
     1355
     1356mv = getMapView()
     1357if mv and mv.editLayer and mv.editLayer.data:
     1358    dummy_relation = Relation()
     1359    selectedRelations = mv.editLayer.data.getSelectedRelations()
     1360
     1361    if not(selectedRelations):
     1362        JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une relation d'itinéraire")
     1363    else:
     1364        print
     1365        for route in selectedRelations:
     1366            newRelation = Relation(route)
     1367            relationChanged = False
     1368            name = route.get('name')
     1369            if name:
     1370                if reNumberDashNumber.match(name):
     1371                    print 'en supprimant le nom lorsqu'il est de la forme ##-##'
     1372                    newRelation.remove('name')
     1373                    relationChanged = True
     1374            else:
     1375                name = ''
     1376            ref = route.get('ref')
     1377            if ref:
     1378                if reNumberDashNumber.match(ref):
     1379                    print 'en supprimant ref lorsqu'elle est de la forme ##-##'
     1380                    newRelation.remove('ref')
     1381                    relationChanged = True
     1382            else:
     1383                ref = ''
     1384            if relationChanged:
     1385                commandsList.append(Command.ChangeCommand(route, newRelation))
     1386               
     1387                Main.main.undoRedo.add(Command.SequenceCommand("Removing name and/or ref " + name + '/' + ref, commandsList))
     1388                commandsList = []
     1389
     1390            rcn_refs = []; route_relation_names = []; memberslist = []
     1391            endnodes = []; prev_endnodes = []
     1392            continuous_forward = True; continuous_backward = True
     1393            prev_role = None; prev_endnodes_before_forward = None; last_endnodes_before_backward = None
     1394            for member in route.getMembers():
     1395                if member.isWay():
     1396                    role = member.getRole()
     1397                    memberslist.append(member)
     1398                    way = member.getWay()
     1399                    #JOptionPane.showMessageDialog(Main.parent, 'way is selected')
     1400                    endnodes = [way.getNode(0), way.getNode(way.nodesCount-1)]
     1401                    notfoundyet = True
     1402                    for endnode in endnodes:
     1403                        # inventorizing of rcn_ref on end nodes
     1404                        rcn_ref = endnode.get('rcn_ref')
     1405                        if rcn_ref:
     1406                            rcn_refs.append(int(rcn_ref))
     1407                            for referrer in endnode.getReferrers():
     1408                                if referrer.getType() is dummy_relation.getType():
     1409                                    if referrer.get('type')=='network' and referrer.get('network')=='rcn':
     1410                                        relname=referrer.get('name')
     1411                                        if relname:
     1412                                            route_relation_names.append(relname)
     1413                                       
     1414                                    elif referrer.get('type')=='collection':
     1415                                        route_relation_names.append('Node not assigned to network yet')
     1416                        # checking for continuity on ways
     1417                        if notfoundyet:
     1418                            if role:
     1419                                if prev_role:
     1420                                    if role=='forward' and prev_role=='forward' and endnode in prev_endnodes:
     1421                                        notfoundyet = False
     1422                                    elif role=='forward' and prev_role=='backward' and endnode in last_endnodes_before_backward:
     1423                                        notfoundyet = False
     1424                                    elif role=='backward' and prev_role=='forward' and endnode in prev_endnodes:
     1425                                        notfoundyet = False
     1426                                    elif role=='backward' and prev_role=='backward' and endnode in prev_endnodes:
     1427                                        notfoundyet = False
     1428                                else:
     1429                                    if role=='forward' and endnode in prev_endnodes:
     1430                                        notfoundyet = False
     1431                                    elif role=='backward' and endnode in prev_endnodes:
     1432                                        notfoundyet = False
     1433                            else:
     1434                                if prev_role:
     1435                                    if prev_role=='forward' and endnode in prev_endnodes:
     1436                                        notfoundyet = False
     1437                                    elif prev_role=='backward' and endnode in last_endnodes_before_backward:
     1438                                        notfoundyet = False
     1439                                else:
     1440                                    if endnode in prev_endnodes:
     1441                                        notfoundyet = False
     1442                    # Analysis of continuity of ways
     1443                    if prev_endnodes and notfoundyet:
     1444                        if role:
     1445                            if role == 'forward':
     1446                                continuous_forward = False
     1447                            elif role == 'backward':
     1448                                continuous_backward = False
     1449                        else:
     1450                            continuous_forward = False
     1451                            continuous_backward = False
     1452                    if role=='forward':
     1453                        if not(prev_endnodes_before_forward):
     1454                            prev_endnodes_before_forward  = prev_endnodes
     1455                    elif prev_role=='forward' and role=='backward':
     1456                        if not(last_endnodes_before_backward):
     1457                            last_endnodes_before_backward = prev_endnodes
     1458                    elif not(role) and prev_role=='backward':
     1459                        prev_endnodes_before_forward = None
     1460                    prev_role = role
     1461                    prev_endnodes = endnodes
     1462            # Drawing conclusions about continuity of ways
     1463            if continuous_forward:
     1464                print 'Itinéraire continu dans la direction vers devant'
     1465            else:
     1466                print 'Itinéraire PAS CONTINU dans la direction vers devant'
     1467            if continuous_backward:
     1468                print 'Itinéraire continu dans la direction vers arrière'
     1469            else:
     1470                print 'Itinéraire PAS CONTINU dans la direction vers arrière'
     1471
     1472            # Drawing conclusions about rcn_refs
     1473            print rcn_refs
     1474            if len(rcn_refs) > 1:
     1475                newRelation = Relation(route)
     1476                relationChanged = False
     1477
     1478                if rcn_refs[0] > rcn_refs[1]:
     1479                    rcn_refs.sort()
     1480                    print 'Inversion de l'ordre des membres'
     1481                    for member in reversed(memberslist):
     1482                        newRelation.addMember( newRelation.getMembersCount(), member)
     1483                        newRelation.removeMember (0)
     1484                    commandsList.append(Command.ChangeCommand(route, newRelation))
     1485                    Main.main.undoRedo.add(Command.SequenceCommand("Flipping order of members", commandsList))
     1486                    commandsList = []
     1487                note = route.get('note')
     1488                newNote = str(rcn_refs[0]).zfill(2) + '-' + str(rcn_refs[1]).zfill(2)
     1489                if not(note) or note != newNote:
     1490                    if not(note): note = 'nothing'
     1491                    newRelation.put('note', newNote)
     1492                    relationChanged = True
     1493                    commandsList.append(Command.ChangeCommand(route, newRelation))
     1494               
     1495                    Main.main.undoRedo.add(Command.SequenceCommand("Changing note from " + note + ' to ' + newNote, commandsList))
     1496                    commandsList = []
     1497
     1498                if len(route_relation_names) > 1 and route_relation_names[0] != route_relation_names[1]:
     1499                    print
     1500                    print 'Il s'agit probablement d'une CONNEXION à un autre réseau'
     1501                    print route_relation_names
     1502            else:
     1503                print 'moins de 2 noeuds terminaux avec rcn_ref trouvés'
     1504}}}
     1505
     1506[wiki:/Help/Plugin/Scripting/Python/RCN_Route_Validator]
     1507
     1508
     1509== Suppression des chemins supplémentaires résultant d'opérations Potlatch  ==
     1510Suppression des chemins supplémentaires résultant des opérations de division des chemins de Potlatch dans le cadre des relations d'interdiction de tourner.
     1511
     1512{{{#!python
     1513#!/bin/jython
     1514
     1515'''
     1516RepairTurns.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
     1517
     1518Ce code est publié sous la licence
     1519"GNU General Public" v2 ou ultérieure.
     1520
     1521La GPL v3 est disponible ici :
     1522https://www.gnu.org/licenses/gpl.html
     1523
     1524Il est livré sans aucune garantie.
     1525
     1526Ce 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.
     1527
     1528Ne fonctionne que pour les interdiction de tourner avec un noeud via
     1529
     1530e.g. Original      : from: Way1, via: Node, to:Way2
     1531     Split         : from: Way1a, from: Way1b, via: Node, to: Way2
     1532     After running : from: Way1b, via: Node, to: Way2
     1533
     1534Ce code illustre comment utiliser Jython pour :
     1535* traiter les éléments sélectionnés
     1536* télécharger les primitives manquantes dans le même thread (blocage)
     1537* traiter, valider et supprimer des membres de relations
     1538
     1539'''
     1540from javax.swing import JOptionPane
     1541from org.openstreetmap.josm import Main
     1542import org.openstreetmap.josm.data.osm.Node as Node
     1543import org.openstreetmap.josm.data.osm.Way as Way
     1544import org.openstreetmap.josm.data.osm.Relation as Relation
     1545import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     1546import org.openstreetmap.josm.data.osm.DataSet as DataSet
     1547import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     1548import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
     1549import org.openstreetmap.josm.io.MultiFetchServerObjectReader as MultiFetchServerObjectReader
     1550import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor as PleaseWaitProgressMonitor
     1551import org.openstreetmap.josm.command as Command
     1552
     1553class RestrictionError(Exception):
     1554    pass
     1555
     1556def getMembers (restriction):
     1557    memberlist = dict()
     1558    for member in restriction.getMembers():
     1559        memberRole = member.getRole()
     1560        if memberRole == "via":
     1561            if member.isNode() and not "via" in memberlist:
     1562                memberlist[memberRole] = [member]
     1563            else:
     1564                raise RestrictionError, "Plus d'un avec rôle via ou avec via mais ce n'est pas un nœud"
     1565        elif memberRole in ("from", "to"):
     1566            if member.isWay():
     1567                try:
     1568                    memberlist[memberRole].append (member)
     1569                except KeyError:
     1570                    memberlist[memberRole] = [member]
     1571            else:
     1572                raise RestrictionError, "avec le rôle From ou to mais n'est pas un chemin"
     1573        else:
     1574            raise RestrictionError, "Rôle inconnu " + memberRole
     1575
     1576    if len(memberlist.keys())<3:
     1577        raise RestrictionError, "Certains rôles manquent : Seulement " + ",".join (memberlist.keys()) + " found"
     1578    return memberlist
     1579
     1580def downloadPrimitives (primitives, editlayer):
     1581    """
     1582        Télécharger une liste de primitives depuis le serveur, et les fusionner dans editlayer.
     1583Blocking.
     1584    """
     1585    monitor = PleaseWaitProgressMonitor()
     1586    monitor.showForegroundDialog()   
     1587
     1588    print "Téléchargement"
     1589    try:
     1590        objectReader = MultiFetchServerObjectReader().append (primitives)
     1591        dataSet = objectReader.parseOsm (monitor)
     1592        editlayer.mergeFrom (dataSet)
     1593        editlayer.onPostDownloadFromServer()
     1594        if (not objectReader.getMissingPrimitives().isEmpty()) :
     1595            raise RestrictionError, "Impossible de télécharger les primitives manquantes"
     1596        print "Téléchargement terminé"
     1597    finally:
     1598        monitor.close()
     1599
     1600def checkIfConnected (node, way, reverse):
     1601    """
     1602        Return (connecté, prochain nœud à comparer (c'est-à-dire l'autre extrémité du nœud) si vrai)
     1603    """
     1604    if (way.isOneway() != 0 and reverse):
     1605        return node == way.lastNode(True), way.firstNode(True) # True: auto process case whan isOneway == -1
     1606    if (way.isOneway() != 0):     # pas d'inversion
     1607        return node == way.firstNode(True), way.lastNode(True)
     1608    if node == way.firstNode():
     1609        return True, way.lastNode()
     1610    if node == way.lastNode():
     1611        return True, way.firstNode()
     1612    return False, node   
     1613
     1614
     1615def repairrestriction (relation, memberlist, editLayer):
     1616    """
     1617        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
     1618    """
     1619    incompleteMembers = relation.getIncompleteMembers()
     1620    if incompleteMembers:
     1621          downloadPrimitives (incompleteMembers, editLayer);       
     1622
     1623    fromRemovalList = []; toRemovalList = []
     1624   
     1625    if len (memberlist["from"]) >= 1:
     1626        currnode = memberlist["via"][0].getNode()
     1627        firstMember = True
     1628        failed = False;
     1629        # trace "from" des membres pour confirmer s'ils sont séparés d'un seul chemin
     1630        for member in reversed(memberlist['from']):
     1631            connected, currnode = checkIfConnected (currnode, member.getWay(), True)
     1632            if not connected:
     1633                if not firstMember:
     1634                    raise RestrictionError, "des chemins non continus du noeud via"
     1635                failed = True
     1636                break
     1637            if not firstMember:
     1638                fromRemovalList.append (member)
     1639            else:
     1640                firstMember = False
     1641
     1642        if failed: # Deuxième tentative en cas d'inversion de la séquence lors du fractionnement
     1643            currnode = memberlist["via"][0].getNode()
     1644            for member in memberlist['from']:
     1645                connected, currnode = checkIfConnected (currnode, member.getWay(), True)
     1646                if not connected:
     1647                    raise RestrictionError, "des chemins non continus du noeud via"
     1648                if not firstMember:
     1649                    fromRemovalList.append (member)
     1650                else:
     1651                    firstMember = False
     1652                                                                       
     1653    if len (memberlist["to"]) >= 1:
     1654        currnode = memberlist["via"][0].getNode()
     1655        firstMember = True
     1656        failed = False
     1657        # trace les membres " to " pour confirmer s'ils ont été séparés d'un chemin
     1658        for member in memberlist['to']:
     1659            connected, currnode = checkIfConnected (currnode, member.getWay(), False)
     1660            if not connected:
     1661                if not firstMember:
     1662                    raise RestrictionError, "chemins to non continus avec le noeud via"
     1663                failed = True
     1664                break
     1665            if not firstMember:
     1666                toRemovalList.append (member)
     1667            else:
     1668                firstMember = False
     1669
     1670        if failed: # Deuxième tentative en cas d'inversion de la séquence lors du fractionnement
     1671            currnode = memberlist["via"][0].getNode()
     1672            for member in reversed(memberlist['to']):
     1673                connected, currnode = checkIfConnected (currnode, member.getWay(), False)
     1674                if not connected:
     1675                    raise RestrictionError, "chemins to non continus avec le noeud via"
     1676                if not firstMember:
     1677                    toRemovalList.append (member)
     1678                else:
     1679                    firstMember = False         
     1680                         
     1681    # pour supprimer les chemins dans fromRemovalList, toRemovalList
     1682    newRelation = Relation(relation)
     1683    waysToRemove = set()
     1684    for removalList in [fromRemovalList, toRemovalList]:
     1685        waysToRemove |= set ([m.getWay() for m in removalList])
     1686    newRelation.removeMembersFor (waysToRemove)
     1687    print "Supprimer le(s) chemin(s) identifiant : " + ",".join ([str(w.getId()) for w in waysToRemove])
     1688    return Command.ChangeCommand (relation, newRelation)   
     1689   
     1690   
     1691validrestrictiontypes = ('only_straight_on', 'only_right_turn', 'only_left_turn', 'no_right_turn', 'no_left_turn', 'no_straight_on', 'no_u_turn')
     1692editLayer = Main.getLayerManager().getEditLayer()
     1693if editLayer and editLayer.data:
     1694    selectedRelations = editLayer.data.getSelectedRelations()
     1695   
     1696    if not(selectedRelations):
     1697        JOptionPane.showMessageDialog(Main.parent, "Veuillez sélectionner une ou plusieurs relations")
     1698    else:
     1699        commandsList = []
     1700        for relation in selectedRelations:
     1701            if relation.get('type') == "restriction" and relation.get('restriction') in validrestrictiontypes:
     1702                try:
     1703                    memberlist = getMembers (relation)
     1704                    if (len (memberlist["from"])) > 1 or (len (memberlist["to"])) > 1 :
     1705                        # Tentative de réparation
     1706                        print "Tentative de réparation",
     1707                        print "relation id: " + str(relation.getId())
     1708                        command = repairrestriction (relation, memberlist, mv.editLayer)
     1709                        print "Succès"                         
     1710                        commandsList.append (command)
     1711                except RestrictionError, e:
     1712                    print str(e), "; relation id: "+ str(relation.getId())
     1713               
     1714       
     1715        Main.main.undoRedo.add(Command.SequenceCommand("Réparation des interdictions de tourner", commandsList))
     1716        commandsList=[]
     1717}}}
     1718
     1719
     1720== Voir également ==
     1721* La version originale de cette page en [wiki:/Help/Plugin/Scripting/Python anglais]
     1722
     1723
     1724----
     1725Retour au [wikitr:/Help/Plugin/Scripting Greffon Scripting] \\
     1726Retour à l'[wikitr:/Plugins Aide des Greffons] \\
     1727Retour à l'[wikitr:/Help Aide Principale]