[[TranslatedPages(revision=18)]] = Kromaĵo -> Skriptado -> Python = == Celo == Kelkaj pliaj ekzemploj en Python: [[PageOutline(2,Enhavotabelo)]] == Konverti vojon kiu konektiĝas al nerompita ĉirkaŭvojo al forko == Konverti vojon kiu konektiĝas al ĉirkaŭvojo al forko konsistanta el 2 unudirektaj vojoj. Dividi la vojon sur ĝia lasta nodo kaj konekti al la 2 nodoj apudaj al la komuna nodo de la ĉirkaŭvojo. Ĉi tiu versio nur funkcias sur nerompitaj ĉirkaŭvojoj. Vidu la sekvan ekzemplon por ĝisdatigita versio. {{{#!python from javax.swing import JOptionPane from org.openstreetmap.josm.gui import MainApplication import org.openstreetmap.josm.command as Command import org.openstreetmap.josm.data.osm.Way as Way editLayer = MainApplication.getLayerManager().getEditLayer() if editLayer and editLayer.data: selected_ways = editLayer.data.getSelectedWays() print selected_ways if not(selected_ways) or len(selected_ways)>1: JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Bonvolu elekti unu vojon kiu konektiĝas al ĉirkaŭvojo") else: for way in selected_ways: if way.get('oneway') in ['yes', '-1']: JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Ĉi tiu vojo havas unudirektan etikedon") else: node_before = None node_after = None common_node = None common_node_becomes_node_before=None #print dir(way) for fln in [way.firstNode(), way.lastNode()]: print 'fln', fln for parentway in fln.getParentWays(): if parentway.get("junction")=='roundabout': for n in parentway.getNodes(): if common_node: # trovita komuna nodo inter elektita vojo kaj # ĉirkaŭvojo en antaŭa iteracio node_after = n # ni estas pretaj ĉi tie break if n.getId() == fln.getId(): # ĉi tiu estas la nodo kiun la ĉirkaŭvojo havas komunan kun la elektita vojo common_node = n if not(node_before): # normale ni renkontis nodon sur la ĉirkaŭvojo # antaŭ ĉi tiu, sed se la komuna nodo estas la unua nodo # de nerompita ĉirkaŭvojo, ni devos preni la lastan # nodon de la ĉirkaŭvojo anstataŭe node_before = parentway.getNodes()[-2] node_after = parentway.getNodes()[1] break # se ne, ni iras tra la buklo unu fojon pli por meti la sekvan # nodon en node_after continue node_before = n if common_node: # se common_node jam estas difinita ĉe ĉi tiu punkto, ĝi signifas ke ĝi estis # la unua nodo de la elektita vojo, # do ĝi devos esti anstataŭigita per node_before en la elektita vojo common_node_becomes_node_before = True adjacent_node_to_split_on = way.getNodes()[1] break else: common_node_becomes_node_before = False adjacent_node_to_split_on = way.getNodes()[-1] if not(common_node) or common_node_becomes_node_before==None: JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Bonvolu elekti vojon kiu konektiĝas al ĉirkaŭvojo") else: print common_node.get('name') print node_before.get('name') print node_after.get('name') commandsList = [] if len(way.getNodes())>2: # dividi lastan segmenton antaŭ ĉirkaŭvojo se necese commandsList.append(Command.SplitWayCommand.split( way, [adjacent_node_to_split_on], [])) MainApplication.undoRedo.add(Command.SequenceCommand( "Dividi elektitan vojon", commandsList)) commandsList = [] # Post dividado trovi la segmenton kiu konektiĝas al la ĉirkaŭvojo denove for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays(): if common_node in waypartconnectedtoroundabout.getNodes(): break if len(way.getNodes())==2: if common_node == waypartconnectedtoroundabout.firstNode(): adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode() else: adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode() # tempo por efektive fari ion # krei kopion de la vojo modified_way = Way(waypartconnectedtoroundabout) # anstataŭigi ĝiajn nodojn, por ke ĝi iĝu forko modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after]) # aldoni unudirektan etikedon modified_way.put('oneway', 'yes') # apliki la ŝanĝojn commandsList.append(Command.ChangeCommand( waypartconnectedtoroundabout, modified_way)) MainApplication.undoRedo.add(Command.SequenceCommand( "Aldoni unudirektan etikedon kaj krei forkan vojon", commandsList)) commandsList = [] # dividi ĉi tiun vojon kie ĝi forkas commandsList.append(Command.SplitWayCommand.split( waypartconnectedtoroundabout, [adjacent_node_to_split_on], [])) MainApplication.undoRedo.add(Command.SequenceCommand( "Dividi forkon en 2 vojojn", commandsList)) commandsList = [] }}} == Konverti vojon kiu konektiĝas al rompita ĉirkaŭvojo al forko == Ĉi tiu skripto faras la samon kiel la antaŭa, sed ĝi ankaŭ funkcias sur ĉirkaŭvojoj kie la vojoj estas rompitaj. Ĝi ne zorgas pri la rilatoj. {{{#!python from javax.swing import JOptionPane from org.openstreetmap.josm.gui import MainApplication import org.openstreetmap.josm.command as Command import org.openstreetmap.josm.data.osm.Way as Way editLayer = MainApplication.getLayerManager().getEditLayer() print '==== Freŝa rulo ====' if editLayer and editLayer.data: selected_ways = editLayer.data.getSelectedWays() print selected_ways if not(selected_ways) or len(selected_ways)>1: JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Bonvolu elekti unu vojon kiu konektiĝas al ĉirkaŭvojo") else: for way in selected_ways: if way.get('oneway') in ['yes', '-1']: JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Ĉi tiu vojo havas unudirektan etikedon") elif way.get('junction') in ['roundabout']: JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Ĉi tiu vojo estas parto de ĉirkaŭvojo") else: node_before = None node_after = None common_node = None common_node_becomes_node_before=None roundabout_way_before = None roundabout_way_after = None for fln in [way.firstNode(), way.lastNode()]: print 'fln', fln for parentway in fln.getParentWays(): if parentway.get("junction")=='roundabout': print parentway.get('name') if parentway.isClosed(): # nerompita ĉirkaŭvojo for n in parentway.getNodes(): if common_node: # trovita komuna nodo inter elektita vojo # kaj ĉirkaŭvojo en antaŭa iteracio node_after = n print node_before.get('name') print node_after.get('name') # ni estas pretaj ĉi tie break if n.getId() == fln.getId(): # ĉi tiu estas la nodo kiun la ĉirkaŭvojo havas komunan kun la elektita vojo common_node = n print common_node.get('name') if not(node_before): # normale ni renkontis nodon sur la ĉirkaŭvojo # antaŭ ĉi tiu, sed se la komuna nodo estas la unua nodo # de nerompita ĉirkaŭvojo, ni devos preni la lastan # nodon de la ĉirkaŭvojo anstataŭe node_before = parentway.getNodes()[-2] node_after = parentway.getNodes()[1] print node_before.get('name') print node_after.get('name') break # se ne, ni iras tra la buklo unu fojon pli por meti la sekvan # nodon en node_after continue node_before = n else: # ĉi tiu estas rompita ĉirkaŭvojo if parentway.firstNode().getId() == fln.getId(): node_after = parentway.getNodes()[1] roundabout_way_after = parentway print 'node after', node_after.get('name') else: node_before = parentway.getNodes()[-2] roundabout_way_before = parentway if node_before and node_after: common_node = fln break if common_node: # se common_node jam estas difinita ĉe ĉi tiu punkto, ĝi signifas ke ĝi estis # la unua nodo de la elektita vojo, # do ĝi devos esti anstataŭigita per node_before en la elektita vojo common_node_becomes_node_before = True break else: common_node_becomes_node_before = False if common_node.getId() == way.firstNode().getId(): adjacent_node_to_split_on = way.getNodes()[1] else: adjacent_node_to_split_on = way.getNodes()[-1] if not(common_node) or ((parentway.isClosed() and common_node_becomes_node_before==None)): JOptionPane.showMessageDialog(MainApplication.getMainFrame(), "Bonvolu elekti vojon kiu konektiĝas al ĉirkaŭvojo") else: commandsList = [] if len(way.getNodes())>2: # dividi lastan segmenton antaŭ ĉirkaŭvojo se necese commandsList.append(Command.SplitWayCommand.split( way, [adjacent_node_to_split_on], [])) MainApplication.undoRedo.add(Command.SequenceCommand( "Dividi elektitan vojon", commandsList)) commandsList = [] # Post dividado trovi la segmenton kiu konektiĝas al la ĉirkaŭvojo denove for waypartconnectedtoroundabout in adjacent_node_to_split_on.getParentWays(): if waypartconnectedtoroundabout.get('junction') == 'roundabout': continue if common_node in waypartconnectedtoroundabout.getNodes(): break if len(way.getNodes())==2: if common_node == waypartconnectedtoroundabout.firstNode(): adjacent_node_to_split_on = waypartconnectedtoroundabout.lastNode() else: adjacent_node_to_split_on = waypartconnectedtoroundabout.firstNode() # tempo por efektive fari ion # krei kopion de la vojo modified_way = Way(waypartconnectedtoroundabout) # anstataŭigi ĝiajn nodojn, por ke ĝi iĝu forko modified_way.setNodes([node_before, adjacent_node_to_split_on, node_after]) # aldoni unudirektan etikedon modified_way.put('oneway', 'yes') # apliki la ŝanĝojn commandsList.append(Command.ChangeCommand( waypartconnectedtoroundabout, modified_way)) MainApplication.undoRedo.add(Command.SequenceCommand( "Aldoni unudirektan etikedon kaj krei forkan vojon", commandsList)) commandsList = [] # dividi ĉi tiun vojon kie ĝi forkas commandsList.append(Command.SplitWayCommand.split( waypartconnectedtoroundabout, [adjacent_node_to_split_on], [])) MainApplication.undoRedo.add(Command.SequenceCommand( "Dividi forkon en 2 vojojn", commandsList)) commandsList = [] if roundabout_way_before and roundabout_way_after: origway = roundabout_way_before roundabout_way_before.addNode(node_after) commandsList.append(Command.ChangeCommand( origway, roundabout_way_before)) origway = roundabout_way_after roundabout_way_after.removeNode(common_node) commandsList.append(Command.ChangeCommand( origway,roundabout_way_after)) # middleway = Way(roundabout_way_after).setNodes( # [node_before, common_node, node_after]) # commandsList.append(Command.AddCommand(editLayer.data, middleway)) # MainApplication.undoRedo.add(Command.SequenceCommand( # "Aldoni vojon sur ĉirkaŭvojo kie forko konektiĝas", commandsList)) commandsList.append(Command.SplitWayCommand.split( roundabout_way_before, [node_before], [])) MainApplication.undoRedo.add(Command.SequenceCommand( "Dividi ĉirkaŭvojon", commandsList)) commandsList = [] }}} == Eksporti kolekton de itineroj al Garmin GPX-dosiero == Eksporti kolekton de itineroj al Garmin GPX-dosiero (ne ekzemplo, ĉar mi ne pensas ke ni plu faras kolektajn rilatojn): {{{#!python #!/bin/jython ''' RWN2Garmin.py - Numeritaj retoj al Garmin GPX-dosiera konvertilo Ĉi tiu kodo estas liberigita sub la GNU General Public License v2 aŭ poste. La GPL v3 estas alirebla ĉi tie: https://www.gnu.org/licenses/gpl.html Ĝi venas sen ia ajn garantio. ''' from javax.swing import JOptionPane, JDialog from java.awt.event import ActionListener, ActionEvent from org.openstreetmap.josm import Main import org.openstreetmap.josm.command as Command import org.openstreetmap.josm.data.osm.Node as Node import org.openstreetmap.josm.data.osm.Way as Way import org.openstreetmap.josm.data.osm.TagCollection as TagCollection import org.openstreetmap.josm.data.osm.DataSet as DataSet import org.openstreetmap.josm.data.osm.RelationMember as RelationMember import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask import org.openstreetmap.josm.io.MultiFetchServerObjectReader as MultiFetchServerObjectReader import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor as PleaseWaitProgressMonitor import org.openstreetmap.josm.command as Command class RestrictionError(Exception): pass def getMembers (restriction): memberlist = dict() for member in restriction.getMembers(): memberRole = member.getRole() if memberRole == "via": if member.isNode() and not "via" in memberlist: memberlist[memberRole] = [member] else: raise RestrictionError, "Pli ol unu via rolo aŭ via ne estas nodo" elif memberRole in ("from", "to"): if member.isWay(): try: memberlist[memberRole].append (member) except KeyError: memberlist[memberRole] = [member] else: raise RestrictionError, "From aŭ to rolo ne estas vojo" else: raise RestrictionError, "Nekonata rolo " + memberRole if len(memberlist.keys())<3: raise RestrictionError, "Iuj roloj mankas: Nur " + ",".join (memberlist.keys()) + " trovita" return memberlist def downloadPrimitives (primitives, editlayer): """ Elŝuti liston de primitivoj de servilo, kaj kunfandi en redaktotavolon. Blokanta. """ monitor = PleaseWaitProgressMonitor() monitor.showForegroundDialog() print "Elŝutante" try: objectReader = MultiFetchServerObjectReader().append (primitives) dataSet = objectReader.parseOsm (monitor) editlayer.mergeFrom (dataSet) editlayer.onPostDownloadFromServer() if (not objectReader.getMissingPrimitives().isEmpty()) : raise RestrictionError, "Ne eblas elŝuti mankantajn primitivojn" print "Elŝuto kompletigita" finally: monitor.close() def checkIfConnected (node, way, reverse): """ Redoni (konektita, sekva nodo por kompari (t.e. alia fino de la nodo) se vera) """ if (way.isOneway() != 0 and reverse): return node == way.lastNode(True), way.firstNode(True) # Vera: aŭtomate prilabori kazon kiam isOneway == -1 if (way.isOneway() != 0): # ne reverse return node == way.firstNode(True), way.lastNode(True) if node == way.firstNode(): return True, way.lastNode() if node == way.lastNode(): return True, way.firstNode() return False, node def repairrestriction (relation, memberlist, editLayer): """ Elŝuti mankantajn membrojn se necese, akiri liston de membroj por forigi, kaj forigi ilin se neniu eraro leviĝas dum kontrolado """ incompleteMembers = relation.getIncompleteMembers() if incompleteMembers: downloadPrimitives (incompleteMembers, editLayer); fromRemovalList = []; toRemovalList = [] if len (memberlist["from"]) >= 1: currnode = memberlist["via"][0].getNode() firstMember = True failed = False; # spuri "from" membrojn por konfirmi ĉu dividitaj de unu vojo for member in reversed(memberlist['from']): connected, currnode = checkIfConnected (currnode, member.getWay(), True) if not connected: if not firstMember: raise RestrictionError, "from vojoj ne kontinuaj de via nodo" failed = True break if not firstMember: fromRemovalList.append (member) else: firstMember = False if failed: # Dua provo en kazo sekvenco inversigita kiam dividita currnode = memberlist["via"][0].getNode() for member in memberlist['from']: connected, currnode = checkIfConnected (currnode, member.getWay(), True) if not connected: raise RestrictionError, "from vojoj ne kontinuaj de via nodo" if not firstMember: fromRemovalList.append (member) else: firstMember = False if len (memberlist["to"]) >= 1: currnode = memberlist["via"][0].getNode() firstMember = True failed = False # spuri "to" membrojn por konfirmi ĉu dividitaj de unu vojo for member in memberlist['to']: connected, currnode = checkIfConnected (currnode, member.getWay(), False) if not connected: if not firstMember: raise RestrictionError, "to vojoj ne kontinuaj de via nodo" failed = True break if not firstMember: toRemovalList.append (member) else: firstMember = False if failed: # Dua provo en kazo sekvenco inversigita kiam dividita currnode = memberlist["via"][0].getNode() for member in reversed(memberlist['to']): connected, currnode = checkIfConnected (currnode, member.getWay(), False) if not connected: raise RestrictionError, "to vojoj ne kontinuaj de via nodo" if not firstMember: toRemovalList.append (member) else: firstMember = False # por forigi vojojn en fromRemovalList, toRemovalList newRelation = Relation(relation) waysToRemove = set() for removalList in [fromRemovalList, toRemovalList]: waysToRemove |= set ([m.getWay() for m in removalList]) newRelation.removeMembersFor (waysToRemove) print "Forigi vojon(jn) id:" + ",".join ([str(w.getId()) for w in waysToRemove]) return Command.ChangeCommand (relation, newRelation) validrestrictiontypes = ('only_straight_on', 'only_right_turn', 'only_left_turn', 'no_right_turn', 'no_left_turn', 'no_straight_on', 'no_u_turn') editLayer = Main.getLayerManager().getEditLayer() if editLayer and editLayer.data: selectedRelations = editLayer.data.getSelectedRelations() if not(selectedRelations): JOptionPane.showMessageDialog(Main.parent, "Bonvolu elekti unu aŭ plurajn rilatojn") else: commandsList = [] for relation in selectedRelations: if relation.get('type') == "restriction" and relation.get('restriction') in validrestrictiontypes: try: memberlist = getMembers (relation) if (len (memberlist["from"])) > 1 or (len (memberlist["to"])) > 1 : # Ripara provo print "Provu ripari", print "rilato id: " + str(relation.getId()) command = repairrestriction (relation, memberlist, mv.editLayer) print "Sukceso" commandsList.append (command) except RestrictionError, e: print str(e), "; rilato id: "+ str(relation.getId()) Main.main.undoRedo.add(Command.SequenceCommand("Ripari turnrestriktojn", commandsList)) commandsList=[] }}} ---- Reen al [wikitr:/Help/Plugin/Scripting Kromaĵa Skriptado] \\ Reen al [wikitr:/Plugins Kromaĵa Helpo] \\ Reen al [wikitr:/Help Ĉefa Helpo]