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


Ignore:
Timestamp:
2025-03-08T20:14:37+01:00 (6 days ago)
Author:
paleid
Comment:

Nb added

Legend:

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

    v1 v1  
     1[[TranslatedPages(revision=18)]]
     2
     3= Plugin -> Skripting -> Python ==
     4== Formål ==
     5Noen flere eksempler i Python:
     6
     7[[PageOutline(2,Innholdsfortegnelse)]]
     8
     9== Konverter en vei som kobler til en usplittet rundkjøring til en forgrening ==
     10Konverter en vei som kobler til en rundkjøring til en forgrening som består av 2 envegsveier. Deler veien på sin siste node og fest den til de 2 nodene ved siden av fellesnoden til rundkjøringsveien. Denne versjonen fungerer bare på usplittede rundkjøringer. Se neste eksempel for en oppdatert versjon.
     11
     12{{{#!python
     13from javax.swing import JOptionPane
     14from org.openstreetmap.josm.gui import MainApplication
     15
     16import org.openstreetmap.josm.command as Command
     17import org.openstreetmap.josm.data.osm.Way as Way
     18
     19editLayer = MainApplication.getLayerManager().getEditLayer()
     20if editLayer and editLayer.data:
     21    selected_ways = editLayer.data.getSelectedWays()
     22    print selected_ways
     23
     24    if not(selected_ways) or len(selected_ways)>1:
     25        JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
     26                                         "Vennligst velg en enkelt vei som kobler til en rundkjøring")
     27    else:
     28        for way in selected_ways:
     29            if way.get('oneway') in ['yes', '-1']:
     30                JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Denne veien har envegsmerke")
     31            else:
     32                node_before = None
     33                node_after = None
     34                common_node = None
     35                common_node_becomes_node_before=None
     36                #print dir(way)
     37                for fln in [way.firstNode(),  way.lastNode()]:
     38                    print 'fln',  fln
     39                    for parentway in fln.getParentWays():
     40                        if parentway.get("junction")=='roundabout':
     41                            for n in parentway.getNodes():
     42                                if common_node:
     43                                    # fant felles node mellom valgt vei og
     44                                    # rundkjøringsvei i forrige iterasjon
     45                                    node_after = n
     46                                    # vi er ferdige her
     47                                    break
     48                                if n.getId() == fln.getId():
     49                                    # dette er noden rundkjøringen har felles med valgt vei
     50                                    common_node = n
     51                                    if not(node_before):
     52                                        # normalt møter vi en node på rundkjøringsveien
     53                                        # før denne, men hvis fellesnoden er den første noden
     54                                        # i en usplittet rundkjøring, må vi ta den siste
     55                                        # noden i rundkjøringen i stedet
     56                                        node_before = parentway.getNodes()[-2]
     57                                        node_after = parentway.getNodes()[1]
     58                                        break
     59                                    # hvis ikke går vi gjennom løkken en gang til for å sette neste
     60                                    # node i node_after
     61                                    continue
     62                                node_before = n
     63                        if common_node:
     64                            # hvis common_node allerede er definert på dette tidspunktet, betyr det at den var
     65                            # den første noden i den valgte veien,
     66                            # så den må erstattes med node_before i den valgte veien
     67                            common_node_becomes_node_before = True
     68                            adjacent_node_to_split_on = way.getNodes()[1]
     69                            break
     70                        else:
     71                            common_node_becomes_node_before = False
     72                            adjacent_node_to_split_on = way.getNodes()[-1]
     73                if not(common_node) or common_node_becomes_node_before==None:
     74                    JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
     75                                               "Vennligst velg en vei som kobler til en rundkjøring")
     76                else:
     77                    print common_node.get('name')
     78                    print node_before.get('name')
     79                    print node_after.get('name')
     80
     81                    commandsList = []
     82                    if len(way.getNodes())>2:
     83                        # del siste segment før rundkjøring hvis nødvendig
     84                        commandsList.append(Command.SplitWayCommand.split(
     85                                    way, [adjacent_node_to_split_on], []))
     86                        MainApplication.undoRedo.add(Command.SequenceCommand(
     87                                    "Del valgt vei", commandsList))
     88                        commandsList = []
     89                    # Etter deling finn segmentet som kobler til rundkjøringen igjen
     90                    for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
     91                        if common_node in waypartconnectedtoroundabout.getNodes():
     92                            break
     93                    if len(way.getNodes())==2:
     94                        if common_node == waypartconnectedtoroundabout.firstNode():
     95                            adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
     96                        else:
     97                            adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
     98                    # tid til å faktisk gjøre noe
     99                    # lag en kopi av veien
     100                    modified_way = Way(waypartconnectedtoroundabout)
     101                    # erstatt nodene slik at den blir en forgrening
     102                    modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
     103                    # legg til envegsmerke
     104                    modified_way.put('oneway', 'yes')
     105                    # bruk endringene
     106                    commandsList.append(Command.ChangeCommand(
     107                                    waypartconnectedtoroundabout, modified_way))
     108                    MainApplication.undoRedo.add(Command.SequenceCommand(
     109                                    "Legg til envegsmerke og lag forgreningsvei", commandsList))
     110                    commandsList = []
     111                    # del denne veien der den forgrener seg
     112                    commandsList.append(Command.SplitWayCommand.split(
     113                                    waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
     114                    MainApplication.undoRedo.add(Command.SequenceCommand(
     115                                    "Del forgrening i 2 veier", commandsList))
     116                    commandsList = []
     117
     118}}}
     119
     120
     121== Konverter en vei som kobler til en splittet rundkjøring til en forgrening ==
     122Dette skriptet gjør det samme som det forrige, men det fungerer også på rundkjøringer der veiene er splittet. Det tar ikke hensyn til relasjoner.
     123
     124{{{#!python
     125from javax.swing import JOptionPane
     126from org.openstreetmap.josm.gui import MainApplication
     127
     128import org.openstreetmap.josm.command as Command
     129import org.openstreetmap.josm.data.osm.Way as Way
     130
     131editLayer = MainApplication.getLayerManager().getEditLayer()
     132print '==== Ny kjøring ===='
     133if editLayer and editLayer.data:
     134    selected_ways = editLayer.data.getSelectedWays()
     135    print selected_ways
     136
     137    if not(selected_ways) or len(selected_ways)>1:
     138        JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Vennligst velg en enkelt vei som kobler til en rundkjøring")
     139    else:
     140        for way in selected_ways:
     141            if way.get('oneway') in ['yes', '-1']:
     142                JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Denne veien har envegsmerke")
     143            elif way.get('junction') in ['roundabout']:
     144                JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Denne veien er en del av en rundkjøring")
     145            else:
     146                node_before = None
     147                node_after = None
     148                common_node = None
     149                common_node_becomes_node_before=None
     150                roundabout_way_before = None
     151                roundabout_way_after = None
     152                for fln in [way.firstNode(),  way.lastNode()]:
     153                    print 'fln',  fln
     154                    for parentway in fln.getParentWays():
     155                        if parentway.get("junction")=='roundabout':
     156                            print parentway.get('name')
     157                            if parentway.isClosed():
     158                                # usplittet rundkjøring
     159                                for n in parentway.getNodes():
     160                                    if common_node:
     161                                        # fant felles node mellom valgt vei
     162                                        # og rundkjøringsvei i forrige iterasjon
     163                                        node_after = n
     164                                        print node_before.get('name')
     165                                        print node_after.get('name')
     166                                        # vi er ferdige her
     167                                        break
     168                                    if n.getId() == fln.getId():
     169                                        # dette er noden rundkjøringen har felles med valgt vei
     170                                        common_node = n
     171                                        print common_node.get('name')
     172                                        if not(node_before):
     173                                            # normalt møter vi en node på rundkjøringsveien
     174                                            # før denne, men hvis fellesnoden er den første noden
     175                                            # i en usplittet rundkjøring, må vi ta den siste
     176                                            # noden i rundkjøringen i stedet
     177                                            node_before = parentway.getNodes()[-2]
     178                                            node_after = parentway.getNodes()[1]
     179                                            print node_before.get('name')
     180                                            print node_after.get('name')
     181                                            break
     182                                        # hvis ikke går vi gjennom løkken en gang til for å sette neste
     183                                        # node i node_after
     184                                        continue
     185                                    node_before = n
     186                            else:
     187                                # dette er en splittet rundkjøring
     188                                if parentway.firstNode().getId() == fln.getId():
     189                                    node_after = parentway.getNodes()[1]
     190                                    roundabout_way_after = parentway
     191                                    print 'node after', node_after.get('name')
     192                                else:
     193                                    node_before = parentway.getNodes()[-2]
     194                                    roundabout_way_before = parentway
     195                                if node_before and node_after:
     196                                    common_node = fln
     197                                    break
     198
     199                            if common_node:
     200                                # hvis common_node allerede er definert på dette tidspunktet, betyr det at den var
     201                                # den første noden i den valgte veien,
     202                                # så den må erstattes med node_before i den valgte veien
     203                                common_node_becomes_node_before = True
     204                                break
     205                            else:
     206                                common_node_becomes_node_before = False
     207                       
     208                if common_node.getId() == way.firstNode().getId():
     209                    adjacent_node_to_split_on = way.getNodes()[1]
     210                else:
     211                    adjacent_node_to_split_on = way.getNodes()[-1]
     212
     213                if not(common_node) or ((parentway.isClosed() and common_node_becomes_node_before==None)):
     214                    JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Vennligst velg en vei som kobler til en rundkjøring")
     215                else:
     216                    commandsList = []
     217                    if len(way.getNodes())>2:
     218                        # del siste segment før rundkjøring hvis nødvendig
     219                        commandsList.append(Command.SplitWayCommand.split(
     220                                    way, [adjacent_node_to_split_on], []))
     221                        MainApplication.undoRedo.add(Command.SequenceCommand(
     222                                    "Del valgt vei", commandsList))
     223                        commandsList = []
     224                    # Etter deling finn segmentet som kobler til rundkjøringen igjen
     225                    for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays():
     226                        if waypartconnectedtoroundabout.get('junction') == 'roundabout':
     227                            continue
     228                        if common_node in waypartconnectedtoroundabout.getNodes():
     229                            break
     230                    if len(way.getNodes())==2:
     231                        if common_node == waypartconnectedtoroundabout.firstNode():
     232                            adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode()
     233                        else:
     234                            adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode()
     235                    # tid til å faktisk gjøre noe
     236                    # lag en kopi av veien
     237                    modified_way = Way(waypartconnectedtoroundabout)
     238                    # erstatt nodene slik at den blir en forgrening
     239                    modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after])
     240                    # legg til envegsmerke
     241                    modified_way.put('oneway', 'yes')
     242                    # bruk endringene
     243                    commandsList.append(Command.ChangeCommand(
     244                                    waypartconnectedtoroundabout, modified_way))
     245                    MainApplication.undoRedo.add(Command.SequenceCommand(
     246                                    "Legg til envegsmerke og lag forgreningsvei", commandsList))
     247                    commandsList = []
     248                    # del denne veien der den forgrener seg
     249                    commandsList.append(Command.SplitWayCommand.split(
     250                                    waypartconnectedtoroundabout, [adjacent_node_to_split_on], []))
     251                    MainApplication.undoRedo.add(Command.SequenceCommand(
     252                                    "Del forgrening i 2 veier", commandsList))
     253                    commandsList = []
     254                   
     255                    if roundabout_way_before and roundabout_way_after:
     256                        origway = roundabout_way_before
     257                        roundabout_way_before.addNode(node_after)
     258                        commandsList.append(Command.ChangeCommand(
     259                                        origway,  roundabout_way_before))
     260                        origway = roundabout_way_after
     261                        roundabout_way_after.removeNode(common_node)
     262                        commandsList.append(Command.ChangeCommand(
     263                                        origway,roundabout_way_after))
     264#                        middleway = Way(roundabout_way_after).setNodes(
     265#                                        [node_before, common_node, node_after])
     266#                        commandsList.append(Command.AddCommand(editLayer.data, middleway))
     267#                        MainApplication.undoRedo.add(Command.SequenceCommand(
     268#                                        "Legg til vei på rundkjøring der forgrening kobler til", commandsList))
     269                        commandsList.append(Command.SplitWayCommand.split(
     270                                        roundabout_way_before, [node_before], []))
     271                        MainApplication.undoRedo.add(Command.SequenceCommand(
     272                                        "Del rundkjøringsvei", commandsList))
     273                        commandsList = []
     274
     275}}}
     276
     277
     278== Eksporter en samling av ruter til Garmin GPX-fil ==
     279Eksporter en samling av ruter til Garmin GPX-fil (ikke et supereksempel, da jeg ikke tror vi gjør samlingsrelasjoner lenger):
     280
     281{{{#!python
     282#!/bin/jython
     283'''
     284RWN2Garmin.py  - Nummererte nettverk til Garmin GPX-fil konverter
     285Denne koden er utgitt under GNU General Public License v2 eller senere.
     286
     287GPL v3 er tilgjengelig her:
     288https://www.gnu.org/licenses/gpl.html
     289
     290Den kommer uten noen form for garanti.
     291'''
     292from javax.swing import JOptionPane, JDialog
     293from java.awt.event import ActionListener, ActionEvent
     294from org.openstreetmap.josm import Main
     295import org.openstreetmap.josm.command as Command
     296import org.openstreetmap.josm.data.osm.Node as Node
     297import org.openstreetmap.josm.data.osm.Way as Way
     298import org.openstreetmap.josm.data.osm.TagCollection as TagCollection
     299import org.openstreetmap.josm.data.osm.DataSet as DataSet
     300import org.openstreetmap.josm.data.osm.RelationMember as RelationMember
     301import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask
     302import org.openstreetmap.josm.io.MultiFetchServerObjectReader as MultiFetchServerObjectReader
     303import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor as PleaseWaitProgressMonitor
     304import org.openstreetmap.josm.command as Command
     305
     306class RestrictionError(Exception):
     307    pass
     308
     309def getMembers (restriction):
     310    memberlist = dict()
     311    for member in restriction.getMembers():
     312        memberRole = member.getRole()
     313        if memberRole == "via":
     314            if member.isNode() and not "via" in memberlist:
     315                memberlist[memberRole] = [member]
     316            else:
     317                raise RestrictionError, "Mer enn én via-rolle eller via er ikke en node"
     318        elif memberRole in ("from", "to"):
     319            if member.isWay():
     320                try:
     321                    memberlist[memberRole].append (member)
     322                except KeyError:
     323                    memberlist[memberRole] = [member]
     324            else:
     325                raise RestrictionError, "From eller to-rolle er ikke en vei"
     326        else:
     327            raise RestrictionError, "Ukjent rolle " + memberRole
     328
     329    if len(memberlist.keys())<3:
     330        raise RestrictionError, "Noen roller mangler: Bare " + ",".join (memberlist.keys()) + " funnet"
     331    return memberlist
     332
     333def downloadPrimitives (primitives, editlayer):
     334    """
     335        Last ned en liste av primitiver fra serveren, og flett inn i redigeringslaget. Blokkerende.
     336    """
     337    monitor = PleaseWaitProgressMonitor()
     338    monitor.showForegroundDialog()   
     339
     340    print "Laster ned"
     341    try:
     342        objectReader = MultiFetchServerObjectReader().append (primitives)
     343        dataSet = objectReader.parseOsm (monitor)
     344        editlayer.mergeFrom (dataSet)
     345        editlayer.onPostDownloadFromServer()
     346        if (not objectReader.getMissingPrimitives().isEmpty()) :
     347            raise RestrictionError, "Kan ikke laste ned manglende primitiver"
     348        print "Nedlasting fullført"   
     349    finally:
     350        monitor.close()
     351
     352def checkIfConnected (node, way, reverse):
     353    """
     354        Returner (koblet, neste node å sammenligne (dvs. andre enden av noden) hvis sant)
     355    """
     356    if (way.isOneway() != 0 and reverse):
     357        return node == way.lastNode(True), way.firstNode(True) # Sant: automatisk prosesser tilfellet når isOneway == -1
     358    if (way.isOneway() != 0):     # ikke reverse
     359        return node == way.firstNode(True), way.lastNode(True)
     360    if node == way.firstNode():
     361        return True, way.lastNode()
     362    if node == way.lastNode():
     363        return True, way.firstNode()
     364    return False, node   
     365
     366
     367def repairrestriction (relation, memberlist, editLayer):
     368    """
     369        Last ned manglende medlemmer hvis nødvendig, få liste over medlemmer å fjerne, og fjern dem hvis ingen feil oppstår under kontroll
     370    """
     371    incompleteMembers = relation.getIncompleteMembers()
     372    if incompleteMembers:
     373          downloadPrimitives (incompleteMembers, editLayer);       
     374
     375    fromRemovalList = []; toRemovalList = []
     376   
     377    if len (memberlist["from"]) >= 1:
     378        currnode = memberlist["via"][0].getNode()
     379        firstMember = True
     380        failed = False;
     381        # spore "from"-medlemmer for å bekrefte om de er delt fra én vei
     382        for member in reversed(memberlist['from']):
     383            connected, currnode = checkIfConnected (currnode, member.getWay(), True)
     384            if not connected:
     385                if not firstMember:
     386                    raise RestrictionError, "from-veier er ikke kontinuerlige fra via-node"
     387                failed = True
     388                break
     389            if not firstMember:
     390                fromRemovalList.append (member)
     391            else:
     392                firstMember = False
     393
     394        if failed: # Andre forsøk i tilfelle sekvensen er reversert ved deling
     395            currnode = memberlist["via"][0].getNode()
     396            for member in memberlist['from']:
     397                connected, currnode = checkIfConnected (currnode, member.getWay(), True)
     398                if not connected:
     399                    raise RestrictionError, "from-veier er ikke kontinuerlige fra via-node"
     400                if not firstMember:
     401                    fromRemovalList.append (member)
     402                else:
     403                    firstMember = False
     404                                                                       
     405    if len (memberlist["to"]) >= 1:
     406        currnode = memberlist["via"][0].getNode()
     407        firstMember = True
     408        failed = False
     409        # spore "to"-medlemmer for å bekrefte om de er delt fra én vei
     410        for member in memberlist['to']:
     411            connected, currnode = checkIfConnected (currnode, member.getWay(), False)
     412            if not connected:
     413                if not firstMember:
     414                    raise RestrictionError, "to-veier er ikke kontinuerlige fra via-node"
     415                failed = True
     416                break
     417            if not firstMember:
     418                toRemovalList.append (member)
     419            else:
     420                firstMember = False
     421
     422        if failed: # Andre forsøk i tilfelle sekvensen er reversert ved deling
     423            currnode = memberlist["via"][0].getNode()
     424            for member in reversed(memberlist['to']):
     425                connected, currnode = checkIfConnected (currnode, member.getWay(), False)
     426                if not connected:
     427                    raise RestrictionError, "to-veier er ikke kontinuerlige fra via-node"
     428                if not firstMember:
     429                    toRemovalList.append (member)
     430                else:
     431                    firstMember = False         
     432                         
     433    # for å fjerne veier i fromRemovalList, toRemovalList         
     434    newRelation = Relation(relation)
     435    waysToRemove = set()
     436    for removalList in [fromRemovalList, toRemovalList]:
     437        waysToRemove |= set ([m.getWay() for m in removalList])
     438    newRelation.removeMembersFor (waysToRemove)
     439    print "Fjern vei(er) id:" + ",".join ([str(w.getId()) for w in waysToRemove])
     440    return Command.ChangeCommand (relation, newRelation)   
     441   
     442   
     443validrestrictiontypes = ('only_straight_on', 'only_right_turn', 'only_left_turn', 'no_right_turn', 'no_left_turn', 'no_straight_on', 'no_u_turn')
     444editLayer = Main.getLayerManager().getEditLayer()
     445if editLayer and editLayer.data:
     446    selectedRelations = editLayer.data.getSelectedRelations()
     447   
     448    if not(selectedRelations):
     449        JOptionPane.showMessageDialog(Main.parent, "Vennligst velg en eller flere relasjoner")
     450    else:
     451        commandsList = []
     452        for relation in selectedRelations:
     453            if relation.get('type') == "restriction" and relation.get('restriction') in validrestrictiontypes:
     454                try:
     455                    memberlist = getMembers (relation)
     456                    if (len (memberlist["from"])) > 1 or (len (memberlist["to"])) > 1 :
     457                        # Reparasjonsforsøk
     458                        print "Prøver å reparere",
     459                        print "relasjon id: " + str(relation.getId())
     460                        command = repairrestriction (relation, memberlist, mv.editLayer)
     461                        print "Suksess"                         
     462                        commandsList.append (command)
     463                except RestrictionError, e:
     464                    print str(e), "; relasjon id: "+ str(relation.getId())
     465               
     466       
     467        Main.main.undoRedo.add(Command.SequenceCommand("Reparer svingrestriksjoner", commandsList))
     468        commandsList=[]
     469}}}
     470
     471
     472----
     473Tilbake til [wikitr:/Help/Plugin/Scripting Plugin Skripting] \\
     474Tilbake til [wikitr:/Plugins Plugin Hjelp] \\
     475Tilbake til [wikitr:/Help Hovedhjelp]