Version 2 (modified by 12 years ago) ( diff ) | ,
---|
#!/bin/jython ''' CheckRouteOrNetworkOrCollectionOfRoutes.jy - Validation of a rcn route relation This code is released under the GNU General Public License v2 or later. The GPL v3 is accessible here: http://www.gnu.org/licenses/gpl.html The GPL v2 is accessible here: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html It comes with no warranty whatsoever. This code illustrates how to use Jython (Python in the scripting plugin of JOSM) to: * loop over all members of a route relation * find out whether the member is a node, a way or a relation * add/change properties of a relation * remove properties of a relation * add members to a relation * remove members from a relation * sort all members backwards * How to set an element selected ''' from javax.swing import JOptionPane from org.openstreetmap.josm import Main import org.openstreetmap.josm.command as Command import org.openstreetmap.josm.data.osm.Node as Node import org.openstreetmap.josm.data.osm.Way as Way import org.openstreetmap.josm.data.osm.Relation as Relation import org.openstreetmap.josm.data.osm.TagCollection as TagCollection import org.openstreetmap.josm.data.osm.DataSet as DataSet import org.openstreetmap.josm.data.osm.RelationMember as RelationMember import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask import org.openstreetmap.josm.actions.DownloadReferrersAction as DownloadReferrersAction import org.openstreetmap.josm.actions.AutoScaleAction as AutoScaleAction import re, time # comment to disable side effect sideEffects = { 'addRouteToNetwork': None, 'removeNameRefKey_xx-yyAndcreated_by': None, 'modifyNoteTo_xx-yy': None, 'flipOrderOfMembers': None, # such that ways go from lower rcn_ref to higher rcn_ref 'sortRouteRelations': None, 'selectObjects': None, 'zoomToSelection': None, #'downloadReferrersForNodes': None, # This will download all ways and relations for nodes with an rcn_ref #'downloadReferrersForWays': None, # This will download all relations for ways that have an endnode with an rcn_ref #'downloadIncompleteMembers': None, 'createWikiReport': None, #'createGarminGPX': None, # not implemented yet #'checkOneWays = False, # not implemented yet } logVerbosity = 10 ''' 10: only report problems that require attention 20: report on collection 30: report on network nodes 40: report on which routes are being checked 50: report everything ''' def getMapView(): if Main.main and Main.main.map: return Main.main.map.mapView else: return None def sortRouteRelation(route, nodesDict, beginAndEndnodes): # TODO This can still be improved a lot. Now it aborts at the first sign of probable failure. # TODO It sorts the simple cases though (i.e. the ones with no forward/backward roles which actually are continuous) nextNode = None routeToReturn = Relation(route) # Which node has the lower rcn_ref? lowestNodeInt = 10000; lowPos = 0 for nodeTuple in beginAndEndnodes: if nodeTuple[0] < lowestNodeInt: lowestNodeInt, nextNode = nodeTuple if not(nextNode): return route ''' node1: way1 node2: way1,way2 node3: way2,way3,way4 node4: way3,way5 node5: way5,way6 node6: node8: way8, way9 node9: way7,way9,way10 node10: way10, way11 w1,w2,w3,w5,w6,w7,w4,w8,w9,w10''' # At this point nextNode contains the unique ID of the node with the lower rcn_ref members=nodesDict[nextNode] processedMembers = {}; inBranch = False #print len(nodesDict) #print dir(route) while lowPos<route.getMembersCount(): #print 'in loop', routeToReturn if len(members) == 1: member = members[0] elif len(members) == 3: # road is splitting or recombining if inBranch: inBranch = False else: inBranch = True # road is splitting, which is the member we need next? # probably the one not going against a oneway restriction for member in members: if member in processedMembers: continue way = member.getWay() oneway = way.get('oneway') if oneway: oneway = oneway.lower() else: oneway = '' if oneway and not(oneway == 'no'): ob=way.get('oneway:bicycle') if ob: ob = ob.lower() else: ob = '' bo=way.get('bicycle:oneway') if bo: bo = bo.lower() else: bo = '' co=way.get('cycleway_opposite') if co: co = co.lower() else: co = '' onewayForBicycle = oneway in ['yes', '1', 'true', '-1'] and not(ob in ['yes', '1', 'true'] or bo in ['yes', '1', 'true'] or co in ['yes', '1', 'true']) if oneway == '-1': pass # TODO this needs to be taken in consideration if way.getNode(0).getUniqueId() == nextNode: break else: member = members[1] if member in processedMembers: member = members[0] processedMembers[member] = True way = member.getWay() routeToReturn.removeMembersFor(way) print 'lowPos',lowPos routeToReturn.addMember(lowPos,member) #routeToReturn.setModified(True) currentNode = nextNode nextNode = way.getNode(way.nodesCount-1).getUniqueId() if currentNode == nextNode: nextNode = way.getNode(0).getUniqueId() if nextNode in nodesDict: members=nodesDict[nextNode] else: break del nodesDict[nextNode] #print len(nodesDict) if len(nodesDict)<3: break lowPos += 1 #print 'before return', routeToReturn return routeToReturn def checkForContinuity(membersList): listIsContinuous = True; prev_endnodes = [] for member in membersList: if member.isWay(): way = member.getWay() if logVerbosity > 49: print way.getKeys() print way.get('name') print way.nodesCount-1, way if way.get('junction') == 'roundabout': endnodes = way.getNodes() else: if way.nodesCount: endnodes = [way.getNode(0), way.getNode(way.nodesCount-1)] else: endnodes = [] foundTheNode = False for endnode in endnodes: if logVerbosity > 49: print endnode, prev_endnodes if endnode in prev_endnodes: foundTheNode = True if prev_endnodes and not(foundTheNode): listIsContinuous = False if logVerbosity > 49: print way print endnodes print prev_endnodes break prev_endnodes = endnodes return listIsContinuous def checkRCNroute(route, aDownloadWasNeeded): if aDownloadWasNeeded: return None, False, '' if 'removeNameRefKey_xx-yyAndcreated_by' in sideEffects: commandsList = [] reNumberDashNumber = re.compile(r'\d+-\d+') newRelation = Relation(route) relationChanged = False created_by = route.get('created_by') if created_by: print 'removing created_by' newRelation.remove('created_by') relationChanged = True name = route.get('name') if name: if reNumberDashNumber.match(name): print 'removing name when it is of the form ##-##' newRelation.remove('name') relationChanged = True else: name = '' ref = route.get('ref') if ref: if reNumberDashNumber.match(ref): print 'removing ref when it is of the form ##-##' newRelation.remove('ref') relationChanged = True else: ref = '' if relationChanged: commandsList.append(Command.ChangeCommand(route, newRelation)) Main.main.undoRedo.add(Command.SequenceCommand("Removing name and/or ref and/or created_by" + name + '/' + ref, commandsList)) commandsList = [] fixme = route.get('fixme') rcn_refs = []; route_relation_names = []; memberslist = []; roleInNetwork = '' sameNodeNumberRepeated = False allWaysgoingFromLowerToHigher = []; allWaysgoingFromHigherToLower = []; branch = None allWaysgoingFromLowerToHigherBeyondEndOfRoute = []; allWaysgoingFromHigherToLowerBeyondEndOfRoute = [] nodesWithrcn_ref = {}; likelyCandidateNodesForActualStartOfRoute = {} tentacle = 0; tentacles = {}; routeHasStarted = False; high_rcn_refEncountered = 0 rcn_refAsInt = None # tentacles is a nested list of all the segments of ways wich are present before the actual start of the route # sequence, UID of node with rcn_ref, list with ways, reference to next tentacle sequence # 1st level: rcn_refs # 2nd level: rcn_ref, tentacle sequence, ways, next tentacle # {40: [[1, [5n], 2], # [2, [3n], 3], # [3, [3n, 5n, 7n, 8n], 0], # [4, [4n], 0] # ], # 58: [[1, [2n], 0], # [2, [7n], 1] # ] # } newRelation = Relation(route); commandslist = []; i=0; roundabout = [] if 'sortRouteRelations' in sideEffects: nodesForSorting = {}; beginAndEndNodes = [] routeMembers = route.getMembers() for member in routeMembers: if member.isWay(): if high_rcn_refEncountered: high_rcn_refEncountered += 1 role = member.getRole() # make a Python list out of the members, in case we want to simply flip all of them # this would happen if we encounter the high rcn_ref before the low rcn_ref memberslist.append(member) way = member.getWay() if logVerbosity > 49: print way.get('name') wayNodes = way.getNodes() notfoundyet = True if logVerbosity > 49: print wayNodes if role in ['forward']: lastNode=wayNodes[-1] else: lastNode=wayNodes[0] lastNodeUid = lastNode.getUniqueId() if lastNodeUid in likelyCandidateNodesForActualStartOfRoute: likelyCandidateNodesForActualStartOfRoute[lastNodeUid] += 1 else: likelyCandidateNodesForActualStartOfRoute[lastNodeUid] = 1 for endnode in wayNodes: endnodeId = endnode.getUniqueId() if 'sortRouteRelations' in sideEffects: if not(endnodeId in nodesForSorting): nodesForSorting[endnodeId] = [] nodesForSorting[endnodeId].append(member) rcn_ref = endnode.get('rcn_ref') if rcn_ref: rcn_refAsInt = int(rcn_ref.replace("(","").replace(")","")) if 'sortRouteRelations' in sideEffects: beginAndEndNodes.append([rcn_refAsInt, endnodeId]) # keep track of distinct rcn_ref numbers in a list if not(rcn_refAsInt in rcn_refs): if len(rcn_refs): high_rcn_refEncountered += 1; tentacle = 0 rcn_refs.append(rcn_refAsInt) else: sameNodeNumberRepeated = True # keep track of node IDs with an rcn_ref on them if not(rcn_refAsInt in nodesWithrcn_ref): nodesWithrcn_ref[rcn_refAsInt] = [] nodesWithrcn_ref[rcn_refAsInt].append(endnodeId) referrersForNode = endnode.getReferrers(); networkNotFoundForNode = True for referrer in referrersForNode: if referrer.getType() is dummy_relation.getType(): # This node belongs to a relation if referrer.get('type') in ['network'] and referrer.get('network') in ['rcn']: # and we have a winner networkNotFoundForNode = False relname=referrer.get('name') if relname: route_relation_names.append(relname) break if networkNotFoundForNode: route_relation_names.append('Node not assigned to network yet') if 'selectObjects' in sideEffects: Main.main.getCurrentDataSet().setSelected(endnode) if 'zoomToSelection' in sideEffects: AutoScaleAction.zoomToSelection() if 'downloadReferrersForNodes' in sideEffects: aDownloadWasNeeded = True print "Downloading referrers for ", endnode.get('rcn_ref'), ' ', wayNodes DownloadReferrersAction.downloadReferrers(mv.editLayer, wayNodes) return None, False, '' else: print "Would download referrers for ", endnode.get('rcn_ref'), ' ', wayNodes # *** Now let's process the ways *** # build at least 2 structures to help check for continuity on ways # possibly there are 'tentacles' before the start or after the end when there are split network nodes if logVerbosity > 49: print 'L2H', allWaysgoingFromLowerToHigher print 'H2L', allWaysgoingFromHigherToLower print 'L2H', allWaysgoingFromLowerToHigherBeyondEndOfRoute print 'H2L', allWaysgoingFromHigherToLowerBeyondEndOfRoute if i==0: lastNodesBeforeSplit = [wayNodes] else: if not(routeHasStarted): if role: if role in ['forward']: firstNode=wayNodes[0] else: firstNode=wayNodes[-1] firstNodeUid = firstNode.getUniqueId() print firstNodeUid, firstNodeUid in likelyCandidateNodesForActualStartOfRoute if firstNodeUid in likelyCandidateNodesForActualStartOfRoute: print likelyCandidateNodesForActualStartOfRoute[firstNodeUid] print likelyCandidateNodesForActualStartOfRoute if firstNodeUid in likelyCandidateNodesForActualStartOfRoute and likelyCandidateNodesForActualStartOfRoute[firstNodeUid]>1: routeHasStarted = True if firstNode.get('rcn_ref'): if logVerbosity > 49: print 'rcn_ref', firstNode.get('rcn_ref'), 'found in ', firstNode.getUniqueId() # This is not the first member anymore and the first node has an rcn_ref and the member has a role, # so we have to assign what we thought was the start of the route to one of our tentacles tentacle +=1; reference = 0; interestingNodeId = None; tentacledescription = [] if allWaysgoingFromLowerToHigher: prevRole = allWaysgoingFromLowerToHigher[-1].getRole() if logVerbosity > 49: print 'prevRoleL2H', prevRole if prevRole in ['forward']: interestingNodeId = allWaysgoingFromLowerToHigher[-1].getWay().getNodes()[-1].getUniqueId() elif prevRole in ['backward']: interestingNodeId = allWaysgoingFromLowerToHigher[-1].getWay().getNodes()[0].getUniqueId() elif allWaysgoingFromHigherToLower: prevRole = allWaysgoingFromHigherToLower[-1].getRole() if logVerbosity > 49: print 'prevRoleH2L', prevRole if prevRole in ['forward']: interestingNodeId = allWaysgoingFromHigherToLower[-1].getWay().getNodes()[0].getUniqueId() elif prevRole in ['backward']: interestingNodeId = allWaysgoingFromHigherToLower[-1].getWay().getNodes()[-1].getUniqueId() if interestingNodeId and firstNode.getUniqueId() == interestingNodeId: reference = tentacle+1 if allWaysgoingFromLowerToHigher: tentacledescription = [tentacle, allWaysgoingFromLowerToHigher, reference] elif allWaysgoingFromHigherToLower: tentacledescription = [tentacle, allWaysgoingFromHigherToLower, reference] allWaysgoingFromLowerToHigher = []; allWaysgoingFromHigherToLower = []; branch = None if tentacledescription: if rcn_refAsInt and not(rcn_refAsInt in tentacles): tentacles[rcn_refAsInt] = [] tentacles[rcn_refAsInt].append(tentacledescription) else: # no role on way means this is the actual start of our route # so, all that went into allWaysgoingFromLowerToHigher etc has to go to the last tentacle routeHasStarted = True if allWaysgoingFromLowerToHigher or allWaysgoingFromHigherToLower: tentacle +=1 if allWaysgoingFromHigherToLower: allWaysgoingFromLowerToHigher # .append(allWaysgoingFromHigherToLower) tentacledescription = [tentacle, allWaysgoingFromLowerToHigher, 0] # allWaysgoingFromHigherToLower was assigned the start of the route in mistake in this case # it should have gone to both 'branches', so we create a shallow copy allWaysgoingFromLowerToHigher = allWaysgoingFromHigherToLower[:]; branch = None if not(rcn_refAsInt in tentacles): tentacles[rcn_refAsInt] = [] tentacles[rcn_refAsInt].append(tentacledescription) if high_rcn_refEncountered > 1: # We're past the first high rcn_ref if role: if role in ['forward']: lastNode=wayNodes[-1] else: lastNode=wayNodes[0] if lastNode.get('rcn_ref'): print 'rcn_ref', lastNode.get('rcn_ref'), 'found in ', lastNode.getUniqueId() tentacle +=1; reference = 0; interestingNodeId = None; tentacledescription = [] if interestingNodeId and lastNode.getUniqueId() == interestingNodeId: reference = tentacle+1 if allWaysgoingFromLowerToHigher: tentacledescription = [tentacle, allWaysgoingFromLowerToHigherBeyondEndOfRoute, reference] elif allWaysgoingFromHigherToLower: tentacledescription = [tentacle, allWaysgoingFromHigherToLowerBeyondEndOfRoute, reference] allWaysgoingFromLowerToHigherBeyondEndOfRoute = []; allWaysgoingFromHigherToLowerBeyondEndOfRoute = []; branch = None if tentacledescription: if rcn_refAsInt and not(rcn_refAsInt in tentacles): tentacles[rcn_refAsInt] = [] tentacles[rcn_refAsInt].append(tentacledescription) if logVerbosity > 49: print tentacle, repr(tentacles) if role and role in ['forward', 'backward']: # if there is a role, it might be part of the route proper when it branches # this is what we suppose, if we encounter another node with a low rcn_ref, we add what we already had # to the tentacles structure and clear fromLowToHigh if not(branch): if wayNodes: if role in ['forward']: lastNodesBeforeSplit = [wayNodes[0]] else: lastNodesBeforeSplit = [wayNodes[-1]] else: return '', True, '|align="right" | way has no nodes||align="right" | {{BrowseRoute|' + str(route.getId()) + '}}||align="right" needs to be downloaded first\n' if logVerbosity > 49: print waynodes if logVerbosity > 29: print 'lastNodesBeforeSplit', lastNodesBeforeSplit print way.getNodesCount(), 'startnode', wayNodes[0], 'endnode', wayNodes[-1] print 'roundabout', roundabout print wayNodes[-1].get('rcn_ref'),not(member.getUniqueId() == routeMembers[-1].getUniqueId()) if role in ['forward'] and (wayNodes[-1] in lastNodesBeforeSplit or wayNodes[-1] in roundabout): branch = 'HigherToLower' elif role in ['backward'] and wayNodes[0] in lastNodesBeforeSplit: branch = 'HigherToLower' elif branch == 'LowerToHigher' and not(allWaysgoingFromHigherToLower) and wayNodes[-1].get('rcn_ref') and not(member.getUniqueId() == routeMembers[-1].getUniqueId()): # This is for when the route starts forked from a different rcn node (split node situation), we don't want it to kick in for the last member of the route branch = 'HigherToLower' elif not(branch == 'HigherToLower'): branch = 'LowerToHigher' print branch if high_rcn_refEncountered < 2: if branch == 'LowerToHigher': allWaysgoingFromLowerToHigher.append(member) elif branch == 'HigherToLower': allWaysgoingFromHigherToLower.append(member) else: if branch == 'LowerToHigher': allWaysgoingFromLowerToHigherBeyondEndOfRoute.append(member) elif branch == 'HigherToLower': allWaysgoingFromHigherToLowerBeyondEndOfRoute.append(member) else: branch = None; roundabout = [] routeHasStarted = True if high_rcn_refEncountered < 2: allWaysgoingFromLowerToHigher.append(member) allWaysgoingFromHigherToLower.append(member) else: allWaysgoingFromLowerToHigherBeyondEndOfRoute.append(member) allWaysgoingFromHigherToLowerBeyondEndOfRoute.append(member) if way.get('junction') == 'roundabout': roundabout = way.getNodes() elif member.isNode(): node = member.getNode() #commandsList.append(Command.ChangeCommand(route, sortedRelation)) #Main.main.undoRedo.add(Command.SequenceCommand("Sorted route relation", commandsList)) i+=1 #if modified: #commandsList.append(Command.ChangeCommand(route, newRelation)) #Main.main.undoRedo.add(Command.SequenceCommand("Removing way which has no nodes", commandsList)) #commandsList = [] continuous_forward = True; continuous_backward = True if len(allWaysgoingFromLowerToHigher) > 1: continuous_forward = checkForContinuity(allWaysgoingFromLowerToHigher) if 'sortRouteRelations' in sideEffects and not(continuous_forward) and not(fixme): sortedRelation = sortRouteRelation(route, nodesForSorting, beginAndEndNodes) if logVerbosity>49: print route print sortedRelation commandsList.append(Command.ChangeCommand(route, sortedRelation)) Main.main.undoRedo.add(Command.SequenceCommand("Sorted route relation", commandsList)) allWaysgoingFromLowerToHigher = []; allWaysgoingFromHigherToLower = [] routeMembers = route.getMembers(); i=0 for member in routeMembers: if member.isWay(): role = member.getRole() if i==0: lastNodesBeforeSplit = [wayNodes] if role and role in ['forward', 'backward']: if not(branch): if role in ['forward']: lastNodesBeforeSplit = [wayNodes[0]] else: lastNodesBeforeSplit = [wayNodes[-1]] if logVerbosity > 29: print 'wayNodes', wayNodes print 'lastNodesBeforeSplit', lastNodesBeforeSplit print way.getNodesCount(), 'startnode', wayNodes[0], 'endnode', wayNodes[-1] print 'roundabout', roundabout if role in ['forward'] and (wayNodes[-1] in lastNodesBeforeSplit or wayNodes[-1] in roundabout): branch = 'HigherToLower' elif role in ['backward'] and wayNodes[0] in lastNodesBeforeSplit: branch = 'HigherToLower' elif wayNodes[-1].get('rcn_ref') and not(member.getUniqueId() == routeMembers[-1].getUniqueId()): # not(allWaysgoingFromHigherToLower) and ## this last part is probably not necessary anymore # This is for when the route starts forked from a different rcn node (split node situation), we don't want it to kick in for the last member of the route branch = 'HigherToLower' elif not(branch == 'HigherToLower'): branch = 'LowerToHigher' print branch if branch == 'LowerToHigher': allWaysgoingFromLowerToHigher.append(member) elif branch == 'HigherToLower': allWaysgoingFromHigherToLower.append(member) else: branch = None; roundabout = [] allWaysgoingFromLowerToHigher.append(member) allWaysgoingFromHigherToLower.append(member) if way.get('junction') == 'roundabout': roundabout = way.getNodes() i+=1 continuous_forward = checkForContinuity(allWaysgoingFromLowerToHigher) #else: else: # a route relation with only one way member continuous_forward = True if len(allWaysgoingFromHigherToLower) > 1: continuous_backward = checkForContinuity(reversed(allWaysgoingFromHigherToLower)) else: # a route relation with only one way member continuous_backward = True print continuous_forward, continuous_backward for rcn_nodeTentacles in tentacles: for seq, tentacleMember, next in tentacles[rcn_nodeTentacles]: print rcn_nodeTentacles, ' ', seq, ' ', next, ' ', checkForContinuity(tentacleMember) # Drawing conclusions about rcn_refs if logVerbosity > 39: print rcn_refs if sameNodeNumberRepeated: rcn_refs.append(rcn_refs[0]) newNote = note = repr(rcn_refs) sortedRelation = route if len(rcn_refs) > 1: #newRelation = Relation(route) relationChanged = False if rcn_refs[0] > rcn_refs[1]: rcn_refs.sort() if len(memberslist)>1 and 'flipOrderOfMembers' in sideEffects: for member in reversed(memberslist): sortedRelation.addMember( sortedRelation.getMembersCount(), member) sortedRelation.removeMember (0) commandsList.append(Command.ChangeCommand(route, sortedRelation)) Main.main.undoRedo.add(Command.SequenceCommand("Flipping order of members", commandsList)) commandsList = [] note = route.get('note') newNote = str(rcn_refs[0]).zfill(2) + '-' + str(rcn_refs[1]).zfill(2) if logVerbosity > 49: print note, newNote if 'modifyNoteTo_xx-yy' in sideEffects: if not(note) or note != newNote: if not(note): note = 'nothing' newRelation.put('note', newNote) relationChanged = True commandsList.append(Command.ChangeCommand(route, newRelation)) Main.main.undoRedo.add(Command.SequenceCommand("Changing note from " + note + ' to ' + newNote, commandsList)) if logVerbosity > 9: print 'Flipping members order for ', note commandsList = [] if len(route_relation_names) > 1 and route_relation_names[0] != route_relation_names[1]: # print 'This is probably a CONNECTION to another network' if logVerbosity > 9: print newNote, route_relation_names roleInNetwork = 'connection' wikiEN = '' else: if logVerbosity > 9: print 'less than 2 end nodes with rcn_ref found for route', newNote wikiEN = 'style="color:red" | ' + repr(rcn_refs) + ' - ?' if fixme and not(continuous_forward or continuous_backward): if logVerbosity > 9: print 'FIXME flag is INCOMPLETE for route', newNote if continuous_forward: wikiCF = 'align="right" | continuous' if logVerbosity > 29: print 'route is continous in the forward direction' else: wikiCF = 'align="right" style="color:red" | NOT continuous' if logVerbosity > 9: print 'route ',newNote,' is NOT CONTINUOUS in the forward direction' if logVerbosity > 49: print 'L2H:', allWaysgoingFromLowerToHigher if continuous_backward: wikiCB = 'align="right" | continuous' if logVerbosity > 29: print 'route is continous in the backward direction' else: wikiCB = 'align="right" style="color:red" | NOT continuous' if logVerbosity > 9: print 'route ',newNote,' is NOT CONTINUOUS in the backward direction' if logVerbosity > 49: print 'H2L: ', allWaysgoingFromHigherToLower print if fixme: wikiFM = 'style="color:red" | ' + fixme else: wikiFM = ' | ' if fixme or not(continuous_forward) or not(continuous_backward) or (len(rcn_refs)<2 and not(route.get('rcn:external_connection'))): problem = True else: problem = False return roleInNetwork, problem, '|align="right" | ' + note + '||align="right" | {{BrowseRoute|' + str(route.getId()) + '}}||align="right" ' + wikiFM + ' ||' + wikiCF + ' ||' + wikiCB + ' ||' + wikiEN + '\n' def checkNetwork(network, aDownloadWasNeeded): name = network.get('name') if logVerbosity>19: print '********************************************' print name print '********************************************' if 'createWikiReport' in sideEffects: wikiReportOnNodes = ('{| class="wikitable" align="left" style="margin:0 0 2em 2em;"\n|-\n|+' + name + '\n|-\n!style="width:2.5em" | Node\n!Link\n! # Roads\n! # Relations\n|-\n') wikiReportOnRelations = ('{| class="wikitable" align="left" style="margin:0 0 2em 2em;"\n|-\n|+' + name + '\n|-\n!style="width:2.5em" | note\n!link\n!fixme\n! forward\n! backward\n! end nodes\n|-\n') i=1 for networkMember in network.getMembers(): if networkMember.isRelation(): routeRelation = networkMember.getRelation() if routeRelation.get('network') == 'rcn': if routeRelation.hasIncompleteMembers(): name = aRelation.get('name') if not(name): name = '' note = aRelation.get('note') if not(note): note = '' network = aRelation.get('network') if not(network): network = '' if 'downloadIncompleteMembers' in sideEffects: aDownloadWasNeeded = True print 'Downloading incomplete members for', note DownloadRelationMemberTask.run(DownloadRelationMemberTask(routeRelation, routeRelation.getIncompleteMembers(), mv.editLayer )) time.sleep(1) continue else: JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete members of the route relations first: ' + network + ' ' + note + ' ' + name) break roleFromRouteCheck, problemReported, wikiReport = checkRCNroute(routeRelation, aDownloadWasNeeded) if problemReported and 'createWikiReport' in sideEffects: wikiReportOnRelations += wikiReport + '\n|-\n' role = networkMember.getRole() if logVerbosity > 29 and role != roleFromRouteCheck: print print 'Role in network is ', role print 'Maybe this should be: ', roleFromRouteCheck if networkMember.isNode(): node = networkMember.getNode() rcn_ref = node.get('rcn_ref') expected_rcn_route_relations = node.get('expected_rcn_route_relations') if expected_rcn_route_relations: expected_rcn_route_relations = int(expected_rcn_route_relations) else: expected_rcn_route_relations = 3 if rcn_ref: if logVerbosity > 39: print rcn_ref referrersForNode = node.getReferrers() networkNotFoundForNode = True for referrer in referrersForNode: if referrer.getType() is dummy_relation.getType(): if referrer.get('type') in ['network'] and referrer.get('network') in ['rcn']: networkNotFoundForNode = False break if networkNotFoundForNode and 'downloadReferrersNodes' in sideEffects: aDownloadWasNeeded = True if 'selectObjects' in sideEffects: Main.main.getCurrentDataSet().setSelected(node) if 'zoomToSelection' in sideEffects: AutoScaleAction.zoomToSelection() #selectedNode = mv.editLayer.data.getSelected() print 'Downloading referrers for ', node.get('rcn_ref') DownloadReferrersAction.downloadReferrers(mv.editLayer, node) rcnNetworkCountForNode = roads = 0 for referrer in referrersForNode: if referrer.getType() is dummy_way.getType(): if referrer.get('highway'): roads += 1 referrersForWay = referrer.getReferrers() if len(referrersForWay) < 1 and 'downloadReferrersForWays' in sideEffects: aDownloadWasNeeded = True if 'selectObjects' in sideEffects: Main.main.getCurrentDataSet().setSelected(referrer) if 'zoomToSelection' in sideEffects: AutoScaleAction.zoomToSelection() print 'Downloading referrers for ', referrer.get('name') , ' ', rcn_ref DownloadReferrersAction.downloadReferrers(mv.editLayer, referrer) for wayReferrer in referrersForWay: if wayReferrer.getType() is dummy_relation.getType(): aRelation = wayReferrer if aRelation.get('type') == 'route' and aRelation.get('network') == 'rcn': rcnNetworkCountForNode+=1 if aRelation.hasIncompleteMembers(): name = aRelation.get('name') if not(name): name = '' note = aRelation.get('note') if not(note): note = '' networkname = aRelation.get('network') if not(networkname): networkname = '' if 'downloadIncompleteMembers' in sideEffects: aDownloadWasNeeded = True print 'Downloading incomplete members for', note DownloadRelationMemberTask.run(DownloadRelationMemberTask(aRelation, aRelation.getIncompleteMembers(), mv.editLayer )) time.sleep(1) continue else: JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete members of the route relations first: ' + networkname + ' ' + note + ' ' + name) break networkMembersList = [] for subMember in network.getMembers(): if subMember.isRelation(): routeRelation = subMember.getRelation() networkMembersList.append(routeRelation.getUniqueId()) routeId = aRelation.getUniqueId() if not(routeId in networkMembersList): if aRelation.get('network') == 'rcn': roleFromRouteCheck, problemReported, wikiReport = checkRCNroute(aRelation, aDownloadWasNeeded) if problemReported and 'createWikiReport' in sideEffects: wikiReportOnRelations += wikiReport + '\n|-\n' if 'addRouteToNetwork' in sideEffects and not(aDownloadWasNeeded): newRelation = Relation(network) newmember = RelationMember(roleFromRouteCheck, aRelation) if logVerbosity > 9: print newRelation.getMembersCount(), ' ',i, ' ', newmember newRelation.addMember( i, newmember) commandsList = [] commandsList.append(Command.ChangeCommand(network, newRelation)) note = aRelation.get('note') if not(note): note = '' Main.main.undoRedo.add(Command.SequenceCommand("Adding " + note + " to network", commandsList)) commandsList = [] if logVerbosity > 9: print 'Added newly found RCN route relation to network: ', note i+=1 if rcnNetworkCountForNode < expected_rcn_route_relations: if logVerbosity > 9: print 'Node ', rcn_ref, ' only has ', rcnNetworkCountForNode, ' rcn routes connected to it' if 'createWikiReport' in sideEffects: wikiReportOnNodes += '|align="right" | ' + rcn_ref + '||align="right" | {{Node|' + str(node.getId()) + '}}||align="right" |' + str(roads) + ' ||align="right" style="color:red" | ' + str(rcnNetworkCountForNode) + '\n|-\n' i+=1 if logVerbosity > 19: print if 'createWikiReport' in sideEffects: wikiReportOnNodes += ('|-\n|}\n') wikiReportOnRelations += ('|-\n|}\n<br style="clear:left;" />\n') fh = open('C:/wikiReport.txt', 'a') fh.write(wikiReportOnNodes) fh.write(wikiReportOnRelations) fh.close() aDownloadWasNeeded = False ''' Since Downloading referrers or missing members happens asynchronously in a separate worker thread the script can run in three modes 1. No downloads allowed/offline run; output mentions that data was incomplete in its reports. 2. Download run; When incomplete items are encountered, they are scheduled to be downloaded. From then on, no more quality checks are performed on the data. All hierarchies are still checked, looking for more incomplete data for which more downloads need to be scheduled. 3. Normal run; All data is available and proper reporting can be performed. ''' dummy_way = Way() dummy_relation = Relation() mv = getMapView() if mv and mv.editLayer and mv.editLayer.data: selectedRelations = mv.editLayer.data.getSelectedRelations() if not(selectedRelations): JOptionPane.showMessageDialog(Main.parent, "Please select a route, network or collection relation") else: if 'createWikiReport' in sideEffects: fh = open('C:/wikiReport.txt', 'w') fh.close() for relation in selectedRelations: if logVerbosity> 49: print relation if relation.hasIncompleteMembers(): if 'downloadIncompleteMembers' in sideEffects: aDownloadWasNeeded = True print 'Downloading referrers for ', str(relation.get('name')), ' ', str(relation.get('note')) DownloadRelationMemberTask.run(DownloadRelationMemberTask(relation, relation.getIncompleteMembers(), mv.editLayer )) continue else: JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete member of the relations first') exit() if relation.get('network') == 'rcn': relationType = relation.get('type') if relationType == 'route': checkRCNroute(relation, aDownloadWasNeeded) elif relationType == 'network': checkNetwork(relation, aDownloadWasNeeded) elif relationType == 'collection': for collectionMember in relation.getMembers(): if collectionMember.isRelation(): networkRelation = collectionMember.getRelation() if networkRelation.hasIncompleteMembers(): name = networkRelation.get('name') if not(name): name = '' networkname = networkRelation.get('network') if not(networkname): networkname = '' if 'downloadIncompleteMembers' in sideEffects: aDownloadWasNeeded = True print 'Downloading referrers for ', name DownloadRelationMemberTask.run(DownloadRelationMemberTask(networkRelation, networkRelation.getIncompleteMembers(), mv.editLayer )) continue else: JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete members of the network relations first:' + networkname + ' ' + name) break checkNetwork(networkRelation, aDownloadWasNeeded) if aDownloadWasNeeded: JOptionPane.showMessageDialog(Main.parent, 'There was incomplete data and downloading mode was initiated,\nNo further quality checks were performed.\nPlease run the script again when all downloads have completed')
Note:
See TracWiki
for help on using the wiki.