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


Ignore:
Timestamp:
2025-06-09T15:35:23+02:00 (2 months ago)
Author:
makmar
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • TabularUnified El:Help/Plugin/Scripting/Python

    v1 v1  
     1[[TranslatedPages(revision=18)]]
     2
     3= Πρόσθετο -> Δημιουργία Σεναρίων -> Python =
     4== Σκοπός ==
     5Μερικά ακόμη παραδείγματα στην Python:
     6
     7[[PageOutline(2,Table of Contents)]]
     8
     9
     10== Μετατροπή γραμμής που συνδέεται με μη διαχωρισμένο κυκλικό κόμβο σε διακλάδωση ==
     11Μετατροπή γραμμής που συνδέεται με κυκλικό κόμβο σε διακλάδωση αποτελούμενη από 2 γραμμές μονής κατεύθυνσης. Η γραμμή διαχωρίζεται στον τελευταίο της κόμβο και συνδέεται στους δύο κόμβους που βρίσκονται δίπλα στον κοινό κόμβο της γραμμής του κυκλικού κόμβου.
     12Αυτή η έκδοση λειτουργεί μόνο σε μη διαχωρισμένους κυκλικούς κόμβους.
     13Δείτε το επόμενο παράδειγμα για μια ενημερωμένη εκδοχή.
     14
     15{{{#!python
     16from javax.swing import JOptionPane
     17from org.openstreetmap.josm.gui import MainApplication
     18
     19import org.openstreetmap.josm.command as Command
     20import org.openstreetmap.josm.data.osm.Way as Way
     21
     22editLayer = MainApplication.getLayerManager().getEditLayer()
     23if editLayer and editLayer.data:
     24    selected_ways = editLayer.data.getSelectedWays()
     25    print selected_ways
     26
     27    if not(selected_ways) or len(selected_ways)>1:
     28        JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
     29                                         "Please select a single way that connects to a roundabout")
     30    else:
     31        for way in selected_ways:
     32            if way.get('oneway') in ['yes', '-1']:
     33                JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "This way has oneway tag set")
     34            else:
     35                node_before = None
     36                node_after = None
     37                common_node = None
     38                common_node_becomes_node_before=None
     39                #print dir(way)
     40                for fln in [way.firstNode(),  way.lastNode()]:
     41                    print 'fln',  fln
     42                    for parentway in fln.getParentWays():
     43                        if parentway.get("junction")=='roundabout':
     44                            for n in parentway.getNodes():
     45                                if common_node:
     46                                    # found common node between selected way and
     47                                    # roundabout way in previous iteration
     48                                    node_after = n
     49                                    # we are done here
     50                                    break
     51                                if n.getId() == fln.getId():
     52                                    # this is the node the roundabout has in common with selected way
     53                                    common_node = n
     54                                    if not(node_before):
     55                                        # normally we encountered a node on the roundabout way
     56                                        # before this one, but if the common node is the first node
     57                                        # of an unsplit roundabout, we will need to take the last
     58                                        # node of the roundabout instead
     59                                        node_before = parentway.getNodes()[-2]
     60                                        node_after = parentway.getNodes()[1]
     61                                        break
     62                                    # if not we go through the loop one more time to put the next
     63                                    # node in node_after
     64                                    continue
     65                                node_before = n
     66                        if common_node:
     67                            # if common_node is already defined at this point, it means it was
     68                            # the first node of the selected way,
     69                            # so it will have to be replaced with node_before in the selected way
     70                            common_node_becomes_node_before = True
     71                            adjacent_node_to_split_on = way.getNodes()[1]
     72                            break
     73                        else:
     74                            common_node_becomes_node_before = False
     75                            adjacent_node_to_split_on = way.getNodes()[-1]
     76                if not(common_node) or common_node_becomes_node_before==None:
     77                    JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
     78                                               "Please select a way that connects to a roundabout")
     79                else:
     80                    print common_node.get('name')
     81                    print node_before.get('name')
     82                    print node_after.get('name')
     83
     84                    commandsList = []
     85                    if len(way.getNodes())>2:
     86                        # split off last segment before roundabout if needed
     87                        commandsList.append(Command.SplitWayCommand.split(
     88                                    way, [adjacent_node_to_split_on], []))
     89                        MainApplication.undoRedo.add(Command.SequenceCommand(
     90                                    "Split selected way", commandsList))
     91                        commandsList = []
     92                    # After splitting find the segment that connects to the roundabout again
     93                    for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
     94                        if common_node in waypartconnectedtoroundabout.getNodes():
     95                            break
     96                    if len(way.getNodes())==2:
     97                        if common_node == waypartconnectedtoroundabout.firstNode():
     98                            adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
     99                        else:
     100                            adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
     101                    # time to actually do something
     102                    # make a copy of the way
     103                    modified_way = Way(waypartconnectedtoroundabout)
     104                    # replace its nodes, so it becomes a fork
     105                    modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
     106                    # add oneway tag
     107                    modified_way.put('oneway', 'yes')
     108                    # apply the changes
     109                    commandsList.append(Command.ChangeCommand(
     110                                    waypartconnectedtoroundabout, modified_way))
     111                    MainApplication.undoRedo.add(Command.SequenceCommand(
     112                                    "Add oneway tag and create forked way", commandsList))
     113                    commandsList = []
     114                    # split this way where it forks
     115                    commandsList.append(Command.SplitWayCommand.split(
     116                                    waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
     117                    MainApplication.undoRedo.add(Command.SequenceCommand(
     118                                    "Split fork into 2 ways", commandsList))
     119                    commandsList = []
     120
     121}}}
     122
     123
     124== Μετατροπή γραμμής που συνδέεται με διαχωρισμένο κυκλικό κόμβο σε διακλάδωση ==
     125Αυτό το σενάριο κάνει το ίδιο με το προηγούμενο, αλλά λειτουργεί και σε κυκλικούς κόμβους όπου οι γραμμές είναι διαχωρισμένες. Δεν λαμβάνει υπόψη του τις σχέσεις.
     126
     127{{{#!python
     128from javax.swing import JOptionPane
     129from org.openstreetmap.josm.gui import MainApplication
     130
     131import org.openstreetmap.josm.command as Command
     132import org.openstreetmap.josm.data.osm.Way as Way
     133
     134editLayer = MainApplication.getLayerManager().getEditLayer()
     135print '==== Fresh run ===='
     136if editLayer and editLayer.data:
     137    selected_ways = editLayer.data.getSelectedWays()
     138    print selected_ways
     139
     140    if not(selected_ways) or len(selected_ways)>1:
     141        JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Please select a single way that connects to a roundabout")
     142    else:
     143        for way in selected_ways:
     144            if way.get('oneway') in ['yes', '-1']:
     145                JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "This way has oneway tag set")
     146            elif way.get('junction') in ['roundabout']:
     147                JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "This way is part of a roundabout")
     148            else:
     149                node_before = None
     150                node_after = None
     151                common_node = None
     152                common_node_becomes_node_before=None
     153                roundabout_way_before = None
     154                roundabout_way_after = None
     155                for fln in [way.firstNode(),  way.lastNode()]:
     156                    print 'fln',  fln
     157                    for parentway in fln.getParentWays():
     158                        if parentway.get("junction")=='roundabout':
     159                            print parentway.get('name')
     160                            if parentway.isClosed():
     161                                # unsplit roundabout
     162                                for n in parentway.getNodes():
     163                                    if common_node:
     164                                        # found common node between selected way
     165                                        # and roundabout way in previous iteration
     166                                        node_after = n
     167                                        print node_before.get('name')
     168                                        print node_after.get('name')
     169                                        # we are done here
     170                                        break
     171                                    if n.getId() == fln.getId():
     172                                        # this is the node the roundabout has in common with selected way
     173                                        common_node = n
     174                                        print common_node.get('name')
     175                                        if not(node_before):
     176                                            # normally we encountered a node on the roundabout way
     177                                            # before this one, but if the common node is the first node
     178                                            # of an unsplit roundabout, we will need to take the last
     179                                            # node of the roundabout instead
     180                                            node_before = parentway.getNodes()[-2]
     181                                            node_after = parentway.getNodes()[1]
     182                                            print node_before.get('name')
     183                                            print node_after.get('name')
     184                                            break
     185                                        # if not we go through the loop one more time to put the next
     186                                        # node in node_after
     187                                        continue
     188                                    node_before = n
     189                            else:
     190                                # this is a split roundabout
     191                                if parentway.firstNode().getId() == fln.getId():
     192                                    node_after = parentway.getNodes()[1]
     193                                    roundabout_way_after = parentway
     194                                    print 'node after', node_after.get('name')
     195                                else:
     196                                    node_before = parentway.getNodes()[-2]
     197                                    roundabout_way_before = parentway
     198                                if node_before and node_after:
     199                                    common_node = fln
     200                                    break
     201
     202                            if common_node:
     203                                # if common_node is already defined at this point, it means it was
     204                                # the first node of the selected way,
     205                                # so it will have to be replaced with node_before in the selected way
     206                                common_node_becomes_node_before = True
     207                                break
     208                            else:
     209                                common_node_becomes_node_before = False
     210                       
     211                if common_node.getId() == way.firstNode().getId():
     212                    adjacent_node_to_split_on = way.getNodes()[1]
     213                else:
     214                    adjacent_node_to_split_on = way.getNodes()[-1]
     215
     216                if not(common_node) or ((parentway.isClosed() and common_node_becomes_node_before==None)):
     217                    JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Please select a way that connects to a roundabout")
     218                else:
     219                    commandsList = []
     220                    if len(way.getNodes())>2:
     221                        # split off last segment before roundabout if needed
     222                        commandsList.append(Command.SplitWayCommand.split(
     223                                    way, [adjacent_node_to_split_on], []))
     224                        MainApplication.undoRedo.add(Command.SequenceCommand(
     225                                    "Split selected way", commandsList))
     226                        commandsList = []
     227                    # After splitting find the segment that connects to the roundabout again
     228                    for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
     229                        if waypartconnectedtoroundabout.get('junction') == 'roundabout':
     230                            continue
     231                        if common_node in waypartconnectedtoroundabout.getNodes():
     232                            break
     233                    if len(way.getNodes())==2:
     234                        if common_node == waypartconnectedtoroundabout.firstNode():
     235                            adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
     236                        else:
     237                            adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
     238                    # time to actually do something
     239                    # make a copy of the way
     240                    modified_way = Way(waypartconnectedtoroundabout)
     241                    # replace its nodes, so it becomes a fork
     242                    modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
     243                    # add oneway tag
     244                    modified_way.put('oneway', 'yes')
     245                    # apply the changes
     246                    commandsList.append(Command.ChangeCommand(
     247                                    waypartconnectedtoroundabout, modified_way))
     248                    MainApplication.undoRedo.add(Command.SequenceCommand(
     249                                    "Add oneway tag and create forked way", commandsList))
     250                    commandsList = []
     251                    # split this way where it forks
     252                    commandsList.append(Command.SplitWayCommand.split(
     253                                    waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
     254                    MainApplication.undoRedo.add(Command.SequenceCommand(
     255                                    "Split fork into 2 ways", commandsList))
     256                    commandsList = []
     257                   
     258                    if roundabout_way_before and roundabout_way_after:
     259                        origway = roundabout_way_before
     260                        roundabout_way_before.addNode(node_after)
     261                        commandsList.append(Command.ChangeCommand(
     262                                        origway,  roundabout_way_before))
     263                        origway = roundabout_way_after
     264                        roundabout_way_after.removeNode(common_node)
     265                        commandsList.append(Command.ChangeCommand(
     266                                        origway,roundabout_way_after))
     267#                        middleway = Way(roundabout_way_after).setNodes(
     268#                                        [node_before, common_node, node_after])
     269#                        commandsList.append(Command.AddCommand(editLayer.data, middleway))
     270#                        MainApplication.undoRedo.add(Command.SequenceCommand(
     271#                                        "Add way on roundabout where fork attaches", commandsList))
     272                        commandsList.append(Command.SplitWayCommand.split(
     273                                        roundabout_way_before, [node_before], []))
     274                        MainApplication.undoRedo.add(Command.SequenceCommand(
     275                                        "Split roundabout way", commandsList))
     276                        commandsList = []
     277
     278}}}
     279
     280
     281== Εξαγωγή συλλογής διαδρομών σε αρχείο Garmin GPX ==
     282Εξαγωγή συλλογής διαδρομών σε αρχείο Garmin GPX (όχι το καλύτερο παράδειγμα, καθώς δεν χρησιμοποιούμε πλέον σχέσεις τύπου συλλογής):
     283
     284{{{#!python
     285#!/bin/jython
     286'''
     287RWN2Garmin.py  - Numbered networks to Garmin GPX file converter
     288This code is released under the GNU General Public License v2 or later.
     289
     290The GPL v3 is accessible here:
     291https://www.gnu.org/licenses/gpl.html
     292
     293It comes with no warranty whatsoever.
     294'''
     295from javax.swing import JOptionPane, JDialog
     296from java.awt.event import ActionListener, ActionEvent
     297from org.openstreetmap.josm import Main
     298import org.openstreetmap.josm.command as Command
     299import org.openstreetmap.josm.data.osm.Node as Node
     300import org.openstreetmap.josm.data.osm.Way as Way
     301import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     302import org.openstreetmap.josm.data.osm.DataSet as DataSet
     303import time
     304
     305f = open('C:/export.gpx', 'w')
     306f.write('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n')
     307f.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://www.topografix.com/GPX/1/1 https://www.topografix.com/GPX/1/1/gpx.xsd">\n')
     308f.write('<!-- All data by OpenStreetMap, licensed under cc-by-sa-2.0 (https://creativecommons.org/licenses/by-sa/2.0/). -->\n')
     309
     310editLayer = Main.getLayerManager().getEditLayer()
     311if editLayer and editLayer.data:
     312    selectedRelations = mv.editLayer.data.getSelectedRelations()
     313
     314    if not(selectedRelations):
     315        JOptionPane.showMessageDialog(Main.parent, "Please select a collection relation")
     316    else:
     317        print
     318        for collection in selectedRelations:
     319            print 'COLLECTION:', collection
     320            for member in collection.getMembers():
     321                print 'MEMBER:',member
     322                if member.isNode():
     323                    node = member.getNode()
     324                    coords = node.getCoor()
     325                    lon = coords.getX()
     326                    lat = coords.getY()
     327                    rwn_ref = node.get('rwn_ref')
     328                    f.write('\t<wpt lat="' + str(lat) + '" lon="' + str(lon) + '">\n')
     329                    if rwn_ref:
     330                        f.write('\t\t<name>' + rwn_ref + '</name>\n')
     331                    f.write('\t</wpt>\n')
     332            for member in collection.getMembers():
     333                if member.isRelation():
     334                    routerelation = member.getRelation()
     335                    f.write('\t<trk>\n')
     336                    networkname =  routerelation.get('network:name')
     337                    if not(networkname):
     338                        networkname =  ''
     339                    else:
     340                        networkname += ' '
     341                    note = routerelation.get('note')
     342                    if not(note): note =  ''
     343                    f.write('\t\t<name>' + networkname + note + '</name>\n')
     344                    f.write('\t\t<src>OpenStreetMap.org</src>\n')
     345                    f.write('\t\t<type>foot</type>\n')
     346                    for routerelmember in routerelation.getMembers():
     347                        if routerelmember.isWay():
     348                            f.write('\t\t<trkseg>\n')
     349                            way=routerelmember.getWay()
     350                            for waynode in way.getNodes():
     351                                 coords = waynode.getCoor()
     352                                 lon = coords.getX()
     353                                 lat = coords.getY()
     354                                 f.write('\t\t\t<trkpt lat="' + str(lat) + '" lon="' + str(lon) + '"> </trkpt>\n')
     355
     356                            f.write('\t\t</trkseg>\n')
     357                    f.write('\t</trk>\n')
     358f.write('</gpx>\n')
     359f.close()
     360}}}
     361
     362
     363== Λήψη των ελλειπόντων γονικών στοιχείων για το επιλεγμένο στοιχείο ==
     364
     365{{{#!python
     366#!/bin/jython
     367'''
     368
     369This code is released under the GNU General
     370Public License v2 or later.
     371
     372The GPL v3 is accessible here:
     373https://www.gnu.org/licenses/gpl.html
     374
     375The GPL v2 is accessible here:
     376https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
     377
     378It comes with no warranty whatsoever.
     379
     380This code illustrates how to use Jython to:
     381* Download all referrers for an element
     382
     383'''
     384from javax.swing import JOptionPane
     385from org.openstreetmap.josm import Main
     386import org.openstreetmap.josm.actions.DownloadReferrersAction as DownloadReferrersAction
     387
     388editLayer = Main.getLayerManager().getEditLayer()
     389if editLayer and editLayer.data:
     390    selectedElements = editLayer.data.getSelected()
     391   
     392    if not(selectedElements):
     393        JOptionPane.showMessageDialog(Main.parent, "Please select an element")
     394    else:
     395        DownloadReferrersAction.downloadReferrers(editLayer, selectedElements)
     396}}}
     397
     398
     399== Λήψη των ελλειπόντων μελών της σχέσης ==
     400
     401{{{
     402#!/bin/jython
     403'''
     404
     405This code is released under the GNU General
     406Public License v2 or later.
     407
     408The GPL v3 is accessible here:
     409https://www.gnu.org/licenses/gpl.html
     410
     411The GPL v2 is accessible here:
     412https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
     413
     414It comes with no warranty whatsoever.
     415
     416This code illustrates how to use Jython to:
     417* Download all missing members of a relation
     418
     419'''
     420from javax.swing import JOptionPane
     421from org.openstreetmap.josm import Main
     422import org.openstreetmap.josm.data.osm.Node as Node
     423import org.openstreetmap.josm.data.osm.Way as Way
     424import org.openstreetmap.josm.data.osm.Relation as Relation
     425import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     426import org.openstreetmap.josm.data.osm.DataSet as DataSet
     427import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     428import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
     429
     430editLayer = Main.getLayerManager().getEditLayer()
     431if editLayer:
     432    selectedRelations = editLayer.data.getSelectedRelations()
     433   
     434    if not(selectedRelations):
     435        JOptionPane.showMessageDialog(Main.parent, "Please select a relation")
     436    else:
     437        for relation in selectedRelations:
     438            if relation.hasIncompleteMembers():
     439                #print dir(relation)
     440                print dir(DownloadRelationMemberTask)
     441                DownloadRelationMemberTask.run(DownloadRelationMemberTask(relation, relation.getIncompleteMembers(), editLayer ))
     442}}}
     443
     444
     445== Επαλήθευση σχέσης διαδρομής rcn ==
     446
     447{{{
     448#!/bin/jython
     449'''
     450- Validation of a rcn route relation
     451
     452This code is released under the GNU General
     453Public License v2 or later.
     454
     455The GPL v3 is accessible here:
     456https://www.gnu.org/licenses/gpl.html
     457
     458The GPL v2 is accessible here:
     459https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
     460
     461It comes with no warranty whatsoever.
     462
     463This code illustrates how to use Jython to:
     464* loop over all members of a route relation
     465* find out whether the member is a node, a way or a relation
     466* add/change properties of a relation
     467* remove properties of a relation
     468* add members to a relation
     469* remove members from a relation
     470* sort all members backwards
     471
     472* How to set an element selected
     473
     474'''
     475from javax.swing import JOptionPane
     476from org.openstreetmap.josm import Main
     477import org.openstreetmap.josm.command as Command
     478import org.openstreetmap.josm.data.osm.Node as Node
     479import org.openstreetmap.josm.data.osm.Way as Way
     480import org.openstreetmap.josm.data.osm.Relation as Relation
     481import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     482import org.openstreetmap.josm.data.osm.DataSet as DataSet
     483import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     484import re
     485
     486commandsList = []
     487reNumberDashNumber = re.compile(r'\d+-\d+')
     488def getMapView():
     489    if Main.main and Main.main.map:
     490        return Main.main.map.mapView
     491    else:
     492        return None
     493
     494mv = getMapView()
     495if mv and mv.editLayer and mv.editLayer.data:
     496    dummy_relation = Relation()
     497    selectedRelations = mv.editLayer.data.getSelectedRelations()
     498
     499    if not(selectedRelations):
     500        JOptionPane.showMessageDialog(Main.parent, "Please select a route relation")
     501    else:
     502        print
     503        for route in selectedRelations:
     504            newRelation = Relation(route)
     505            relationChanged = False
     506            name = route.get('name')
     507            if name:
     508                if reNumberDashNumber.match(name):
     509                    print 'removing name when it is of the form ##-##'
     510                    newRelation.remove('name')
     511                    relationChanged = True
     512            else:
     513                name = ''
     514            ref = route.get('ref')
     515            if ref:
     516                if reNumberDashNumber.match(ref):
     517                    print 'removing ref when it is of the form ##-##'
     518                    newRelation.remove('ref')
     519                    relationChanged = True
     520            else:
     521                ref = ''
     522            if relationChanged:
     523                commandsList.append(Command.ChangeCommand(route, newRelation))
     524               
     525                Main.main.undoRedo.add(Command.SequenceCommand("Removing name and/or ref " + name + '/' + ref, commandsList))
     526                commandsList = []
     527
     528            rcn_refs = []; route_relation_names = []; memberslist = []
     529            endnodes = []; prev_endnodes = []
     530            continuous_forward = True; continuous_backward = True
     531            prev_role = None; prev_endnodes_before_forward = None; last_endnodes_before_backward = None
     532            for member in route.getMembers():
     533                if member.isWay():
     534                    role = member.getRole()
     535                    memberslist.append(member)
     536                    way = member.getWay()
     537                    #JOptionPane.showMessageDialog(Main.parent, 'way is selected')
     538                    endnodes = [way.getNode(0), way.getNode(way.nodesCount-1)]
     539                    notfoundyet = True
     540                    for endnode in endnodes:
     541                        # inventorizing of rcn_ref on end nodes
     542                        rcn_ref = endnode.get('rcn_ref')
     543                        if rcn_ref:
     544                            rcn_refs.append(int(rcn_ref))
     545                            for referrer in endnode.getReferrers():
     546                                if referrer.getType() is dummy_relation.getType():
     547                                    if referrer.get('type')=='network' and referrer.get('network')=='rcn':
     548                                        relname=referrer.get('name')
     549                                        if relname:
     550                                            route_relation_names.append(relname)
     551                                       
     552                                    elif referrer.get('type')=='collection':
     553                                        route_relation_names.append('Node not assigned to network yet')
     554                        # checking for continuity on ways
     555                        if notfoundyet:
     556                            if role:
     557                                if prev_role:
     558                                    if role=='forward' and prev_role=='forward' and endnode in prev_endnodes:
     559                                        notfoundyet = False
     560                                    elif role=='forward' and prev_role=='backward' and endnode in last_endnodes_before_backward:
     561                                        notfoundyet = False
     562                                    elif role=='backward' and prev_role=='forward' and endnode in prev_endnodes:
     563                                        notfoundyet = False
     564                                    elif role=='backward' and prev_role=='backward' and endnode in prev_endnodes:
     565                                        notfoundyet = False
     566                                else:
     567                                    if role=='forward' and endnode in prev_endnodes:
     568                                        notfoundyet = False
     569                                    elif role=='backward' and endnode in prev_endnodes:
     570                                        notfoundyet = False
     571                            else:
     572                                if prev_role:
     573                                    if prev_role=='forward' and endnode in prev_endnodes:
     574                                        notfoundyet = False
     575                                    elif prev_role=='backward' and endnode in last_endnodes_before_backward:
     576                                        notfoundyet = False
     577                                else:
     578                                    if endnode in prev_endnodes:
     579                                        notfoundyet = False
     580                    # Analysis of continuity of ways
     581                    if prev_endnodes and notfoundyet:
     582                        if role:
     583                            if role == 'forward':
     584                                continuous_forward = False
     585                            elif role == 'backward':
     586                                continuous_backward = False
     587                        else:
     588                            continuous_forward = False
     589                            continuous_backward = False
     590                    if role=='forward':
     591                        if not(prev_endnodes_before_forward):
     592                            prev_endnodes_before_forward  = prev_endnodes
     593                    elif prev_role=='forward' and role=='backward':
     594                        if not(last_endnodes_before_backward):
     595                            last_endnodes_before_backward = prev_endnodes
     596                    elif not(role) and prev_role=='backward':
     597                        prev_endnodes_before_forward = None
     598                    prev_role = role
     599                    prev_endnodes = endnodes
     600            # Drawing conclusions about continuity of ways
     601            if continuous_forward:
     602                print 'route is continous in the forward direction'
     603            else:
     604                print 'route is NOT CONTINUOUS in the forward direction'
     605            if continuous_backward:
     606                print 'route is continous in the backward direction'
     607            else:
     608                print 'route is NOT CONTINUOUS in the backward direction'
     609
     610            # Drawing conclusions about rcn_refs
     611            print rcn_refs
     612            if len(rcn_refs) > 1:
     613                newRelation = Relation(route)
     614                relationChanged = False
     615
     616                if rcn_refs[0] > rcn_refs[1]:
     617                    rcn_refs.sort()
     618                    print 'Flipping members order'
     619                    for member in reversed(memberslist):
     620                        newRelation.addMember( newRelation.getMembersCount(), member)
     621                        newRelation.removeMember (0)
     622                    commandsList.append(Command.ChangeCommand(route, newRelation))
     623                    Main.main.undoRedo.add(Command.SequenceCommand("Flipping order of members", commandsList))
     624                    commandsList = []
     625                note = route.get('note')
     626                newNote = str(rcn_refs[0]).zfill(2) + '-' + str(rcn_refs[1]).zfill(2)
     627                if not(note) or note != newNote:
     628                    if not(note): note = 'nothing'
     629                    newRelation.put('note', newNote)
     630                    relationChanged = True
     631                    commandsList.append(Command.ChangeCommand(route, newRelation))
     632               
     633                    Main.main.undoRedo.add(Command.SequenceCommand("Changing note from " + note + ' to ' + newNote, commandsList))
     634                    commandsList = []
     635
     636                if len(route_relation_names) > 1 and route_relation_names[0] != route_relation_names[1]:
     637                    print
     638                    print 'This is probably a CONNECTION to another network'
     639                    print route_relation_names
     640            else:
     641                print 'less than 2 end nodes with rcn_ref found'
     642}}}
     643
     644[wiki:/Help/Plugin/Scripting/Python/RCN_Route_Validator]
     645
     646
     647== Αφαίρεση επιπλέον γραμμών που προέκυψαν από ενέργειες στο Potlatch ==
     648Αφαίρεση επιπλέον γραμμών που προέκυψαν από διαχωρισμό γραμμών στο Potlatch σε σχέσεις περιορισμού στροφής
     649
     650{{{#!python
     651#!/bin/jython
     652
     653'''
     654RepairTurns.py  - Remove extra ways resulting from Potlatch way split operations under turn restriction relations
     655
     656This code is released under the GNU General
     657Public License v2 or later.
     658
     659The GPL v3 is accessible here:
     660https://www.gnu.org/licenses/gpl.html
     661
     662It comes with no warranty whatsoever.
     663
     664This code Loops through selected turn restriction relations, trying to remove ways split from originally the same way (with to / from roles) under turn restriction relations which should no longer remain as members of these relations, as a result of a Potlatch issue: https://trac.openstreetmap.org/ticket/3254
     665
     666Only works for turn restrictions with one via node
     667
     668e.g. Original      : from: Way1, via: Node, to:Way2
     669     Split         : from: Way1a, from: Way1b, via: Node, to: Way2
     670     After running : from: Way1b, via: Node, to: Way2
     671
     672This code illustrates how to use Jython to:
     673* process selected items
     674* download missing primitives in the same thread (blocking)
     675* process, validate and remove members from relations
     676
     677'''
     678from javax.swing import JOptionPane
     679from org.openstreetmap.josm import Main
     680import org.openstreetmap.josm.data.osm.Node as Node
     681import org.openstreetmap.josm.data.osm.Way as Way
     682import org.openstreetmap.josm.data.osm.Relation as Relation
     683import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     684import org.openstreetmap.josm.data.osm.DataSet as DataSet
     685import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     686import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
     687import org.openstreetmap.josm.io.MultiFetchServerObjectReader as MultiFetchServerObjectReader
     688import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor as PleaseWaitProgressMonitor
     689import org.openstreetmap.josm.command as Command
     690
     691class RestrictionError(Exception):
     692    pass
     693
     694def getMembers (restriction):
     695    memberlist = dict()
     696    for member in restriction.getMembers():
     697        memberRole = member.getRole()
     698        if memberRole == "via":
     699            if member.isNode() and not "via" in memberlist:
     700                memberlist[memberRole] = [member]
     701            else:
     702                raise RestrictionError, "More than one via role or via not a node"
     703        elif memberRole in ("from", "to"):
     704            if member.isWay():
     705                try:
     706                    memberlist[memberRole].append (member)
     707                except KeyError:
     708                    memberlist[memberRole] = [member]
     709            else:
     710                raise RestrictionError, "From or to role not a way"
     711        else:
     712            raise RestrictionError, "Unknown role " + memberRole
     713
     714    if len(memberlist.keys())<3:
     715        raise RestrictionError, "Some roles missing: Only " + ",".join (memberlist.keys()) + " found"
     716    return memberlist
     717
     718def downloadPrimitives (primitives, editlayer):
     719    """
     720        Download a list of primitives from server, and merge into editlayer. Blocking.
     721    """
     722    monitor = PleaseWaitProgressMonitor()
     723    monitor.showForegroundDialog()   
     724
     725    print "Downloading"
     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, "Unable to download missing primitives"
     733        print "Download completed"   
     734    finally:
     735        monitor.close()
     736
     737def checkIfConnected (node, way, reverse):
     738    """
     739        Return (connected, next node to compare (i.e. other end of the node) if true)
     740    """
     741    if (way.isOneway() != 0 and reverse):
     742        return node == way.lastNode(True), way.firstNode(True) # True: auto process case when isOneway == -1
     743    if (way.isOneway() != 0):     # not reverse
     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        Download missing members if needed, get list of members to remove, and remove them if no error raised during checking
     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" members to confirm if split from one way
     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, "from ways not continuous from via node"
     772                failed = True
     773                break
     774            if not firstMember:
     775                fromRemovalList.append (member)
     776            else:
     777                firstMember = False
     778
     779        if failed: # Second attempt in case sequence reversed when split
     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, "from ways not continuous from via node"
     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 "to" members to confirm if split from one way
     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, "to ways not continuous from via node"
     800                failed = True
     801                break
     802            if not firstMember:
     803                toRemovalList.append (member)
     804            else:
     805                firstMember = False
     806
     807        if failed: # Second attempt in case sequence reversed when split
     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, "to ways not continuous from via node"
     813                if not firstMember:
     814                    toRemovalList.append (member)
     815                else:
     816                    firstMember = False         
     817                         
     818    # to remove ways in 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 "Remove way(s) id:" + ",".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, "Please select one or more 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                        # Repair attempt
     843                        print "Attempt repair",
     844                        print "relation id: " + str(relation.getId())
     845                        command = repairrestriction (relation, memberlist, mv.editLayer)
     846                        print "Success"                         
     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("Repair turn restrictions", commandsList))
     853        commandsList=[]
     854}}}
     855
     856
     857----
     858Πίσω στο [wikitr:/Help/Plugin/Scripting Πρόσθετο Δημιουργίας Σεναρίων] \\
     859Πίσω στη [wikitr:/Plugins Βοήθεια Πρόσθετων] \\
     860Πίσω στη [wikitr:/Help Βασική Βοήθεια]
     861