| 1 | |
| 2 | {{{ |
| 3 | #!/bin/jython |
| 4 | ''' |
| 5 | CheckRouteOrNetworkOrCollectionOfRoutes.jy |
| 6 | - Validation of a rcn route, network or collection of networks relation |
| 7 | - Depending on what is selected in JOSM when invoked |
| 8 | |
| 9 | This code is released under the GNU General |
| 10 | Public License v2 or later. |
| 11 | |
| 12 | The GPL v3 is accessible here: |
| 13 | http://www.gnu.org/licenses/gpl.html |
| 14 | |
| 15 | The GPL v2 is accessible here: |
| 16 | http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
| 17 | |
| 18 | It comes with no warranty whatsoever. |
| 19 | |
| 20 | This code illustrates how to use Jython (Python in the scripting plugin of JOSM) to: |
| 21 | * loop over all members of a route relation |
| 22 | * find out whether the member is a node, a way or a relation |
| 23 | * add/change properties of a relation |
| 24 | * remove properties of a relation |
| 25 | * add members to a relation |
| 26 | * remove members from a relation |
| 27 | * sort all members backwards |
| 28 | |
| 29 | * How to set an element selected |
| 30 | |
| 31 | ''' |
| 32 | from javax.swing import JOptionPane |
| 33 | from org.openstreetmap.josm import Main |
| 34 | import org.openstreetmap.josm.command as Command |
| 35 | import org.openstreetmap.josm.data.osm.Node as Node |
| 36 | import org.openstreetmap.josm.data.osm.Way as Way |
| 37 | import org.openstreetmap.josm.data.osm.Relation as Relation |
| 38 | import org.openstreetmap.josm.data.osm.TagCollection as TagCollection |
| 39 | import org.openstreetmap.josm.data.osm.DataSet as DataSet |
| 40 | import org.openstreetmap.josm.data.osm.RelationMember as RelationMember |
| 41 | import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask as DownloadRelationMemberTask |
| 42 | import org.openstreetmap.josm.actions.DownloadReferrersAction as DownloadReferrersAction |
| 43 | import org.openstreetmap.josm.actions.AutoScaleAction as AutoScaleAction |
| 44 | import re, time |
| 45 | |
| 46 | # comment to disable side effect |
| 47 | sideEffects = { |
| 48 | 'addRouteToNetwork': None, |
| 49 | 'removeNameRefKey_xx-yyAndcreated_by': None, |
| 50 | 'modifyNoteTo_xx-yy': None, |
| 51 | 'flipOrderOfMembers': None, # such that ways go from lower rcn_ref to higher rcn_ref |
| 52 | 'sortRouteRelations': None, |
| 53 | 'selectObjects': None, |
| 54 | 'zoomToSelection': None, |
| 55 | #'downloadReferrersForNodes': None, # This will download all ways and relations for nodes with an rcn_ref |
| 56 | #'downloadReferrersForWays': None, # This will download all relations for ways that have an endnode with an rcn_ref |
| 57 | 'downloadIncompleteMembers': None, |
| 58 | 'createWikiReport': None, |
| 59 | 'createGarminGPX': None, |
| 60 | #'checkOneWays = False, # not implemented yet |
| 61 | } |
| 62 | |
| 63 | logVerbosity = 10 |
| 64 | ''' |
| 65 | 10: only report problems that need fixing |
| 66 | 20: report on collection |
| 67 | 30: report on network nodes |
| 68 | 40: report on which routes are being checked |
| 69 | 50: report everything |
| 70 | ''' |
| 71 | def getMapView(): |
| 72 | if Main.main and Main.main.map: |
| 73 | return Main.main.map.mapView |
| 74 | else: |
| 75 | return None |
| 76 | |
| 77 | def sortRouteRelation(route, nodesDict, beginAndEndnodes): |
| 78 | # TODO This can still be improved a lot. Now it aborts at the first sign of probable failure. |
| 79 | # TODO It sorts the simple cases though (i.e. the ones with no forward/backward roles which actually are continuous) |
| 80 | nextNode = None |
| 81 | routeToReturn = Relation(route) |
| 82 | ##print dir (routeToReturn) |
| 83 | #routeToReturn.clearOsmId() |
| 84 | lowestNodeInt = 10000; lowPos = 0 |
| 85 | for nodeTuple in beginAndEndnodes: |
| 86 | if nodeTuple[0] < lowestNodeInt: |
| 87 | lowestNodeInt, nextNode = nodeTuple |
| 88 | if not(nextNode): |
| 89 | return route |
| 90 | members=nodesDict[nextNode] |
| 91 | processedMembers = {} |
| 92 | #print len(nodesDict) |
| 93 | #print dir(route) |
| 94 | while lowPos<route.getMembersCount(): |
| 95 | #print 'in loop', routeToReturn |
| 96 | if len(members) == 1: |
| 97 | member = members[0] |
| 98 | else: |
| 99 | member = members[1] |
| 100 | if member in processedMembers: member = members[0] |
| 101 | processedMembers[member] = True |
| 102 | way = member.getWay() |
| 103 | routeToReturn.removeMembersFor(way) |
| 104 | routeToReturn.addMember(lowPos,member) |
| 105 | #routeToReturn.setModified(True) |
| 106 | currentNode = nextNode |
| 107 | nextNode = way.getNode(way.nodesCount-1).getUniqueId() |
| 108 | if currentNode == nextNode: |
| 109 | nextNode = way.getNode(0).getUniqueId() |
| 110 | if nextNode in nodesDict: |
| 111 | members=nodesDict[nextNode] |
| 112 | else: |
| 113 | break |
| 114 | del nodesDict[nextNode] |
| 115 | #print len(nodesDict) |
| 116 | if len(nodesDict)<3: break |
| 117 | lowPos += 1 |
| 118 | #print 'before return', routeToReturn |
| 119 | return routeToReturn |
| 120 | |
| 121 | def checkForContinuity(membersList): |
| 122 | listIsContinuous = True; prev_endnodes = [] |
| 123 | for member in membersList: |
| 124 | if member.isWay(): |
| 125 | way = member.getWay() |
| 126 | if logVerbosity > 50: print dir(way) |
| 127 | if logVerbosity > 49: |
| 128 | print way.getKeys() |
| 129 | print way.get('name') |
| 130 | print way.nodesCount-1, way |
| 131 | if way.get('junction') == 'roundabout': |
| 132 | endnodes = way.getNodes() |
| 133 | else: |
| 134 | if way.nodesCount: |
| 135 | endnodes = [way.getNode(0), way.getNode(way.nodesCount-1)] |
| 136 | else: |
| 137 | endnodes = [] |
| 138 | foundTheNode = False |
| 139 | for endnode in endnodes: |
| 140 | if logVerbosity > 49: print endnode, prev_endnodes |
| 141 | if endnode in prev_endnodes: |
| 142 | foundTheNode = True |
| 143 | if prev_endnodes and not(foundTheNode): |
| 144 | listIsContinuous = False |
| 145 | if logVerbosity > 49: |
| 146 | print way |
| 147 | print endnodes |
| 148 | print prev_endnodes |
| 149 | break |
| 150 | prev_endnodes = endnodes |
| 151 | return listIsContinuous |
| 152 | |
| 153 | def checkRCNroute(route): |
| 154 | if 'removeNameRefKey_xx-yyAndcreated_by' in sideEffects: |
| 155 | commandsList = [] |
| 156 | reNumberDashNumber = re.compile(r'\d+-\d+') |
| 157 | newRelation = Relation(route) |
| 158 | relationChanged = False |
| 159 | created_by = route.get('created_by') |
| 160 | if created_by: |
| 161 | print 'removing created_by' |
| 162 | newRelation.remove('created_by') |
| 163 | relationChanged = True |
| 164 | name = route.get('name') |
| 165 | if name: |
| 166 | if reNumberDashNumber.match(name): |
| 167 | print 'removing name when it is of the form ##-##' |
| 168 | newRelation.remove('name') |
| 169 | relationChanged = True |
| 170 | else: |
| 171 | name = '' |
| 172 | ref = route.get('ref') |
| 173 | if ref: |
| 174 | if reNumberDashNumber.match(ref): |
| 175 | print 'removing ref when it is of the form ##-##' |
| 176 | newRelation.remove('ref') |
| 177 | relationChanged = True |
| 178 | else: |
| 179 | ref = '' |
| 180 | if relationChanged: |
| 181 | commandsList.append(Command.ChangeCommand(route, newRelation)) |
| 182 | |
| 183 | Main.main.undoRedo.add(Command.SequenceCommand("Removing name and/or ref and/or created_by" + name + '/' + ref, commandsList)) |
| 184 | commandsList = [] |
| 185 | |
| 186 | fixme = route.get('fixme') == 'incomplete' |
| 187 | rcn_refs = []; route_relation_names = []; memberslist = []; roleInNetwork = '' |
| 188 | sameNodeNumberRepeated = False |
| 189 | allWaysgoingFromLowerToHigher = []; allWaysgoingFromHigherToLower = []; branch = None |
| 190 | newRelation = Relation(route); commandslist = []; i=0; roundabout = [] |
| 191 | |
| 192 | if 'sortRouteRelations' in sideEffects: nodesForSorting = {}; beginAndEndNodes = [] |
| 193 | routeMembers = route.getMembers() |
| 194 | for member in routeMembers: |
| 195 | if member.isWay(): |
| 196 | role = member.getRole() |
| 197 | memberslist.append(member) |
| 198 | way = member.getWay() |
| 199 | # print way.get('name') |
| 200 | wayNodes = way.getNodes() |
| 201 | |
| 202 | notfoundyet = True |
| 203 | for endnode in wayNodes: |
| 204 | if 'sortRouteRelations' in sideEffects: |
| 205 | endnodeId = endnode.getUniqueId() |
| 206 | if not(endnodeId in nodesForSorting): |
| 207 | nodesForSorting[endnodeId] = [] |
| 208 | nodesForSorting[endnodeId].append(member) |
| 209 | |
| 210 | rcn_ref = endnode.get('rcn_ref') |
| 211 | if rcn_ref: |
| 212 | rcn_refAsInt = int(rcn_ref) |
| 213 | if 'sortRouteRelations' in sideEffects: beginAndEndNodes.append([rcn_refAsInt, endnodeId]) |
| 214 | if not(rcn_refAsInt in rcn_refs): |
| 215 | rcn_refs.append(rcn_refAsInt) |
| 216 | else: |
| 217 | sameNodeNumberRepeated = True |
| 218 | referrersForNode = endnode.getReferrers(); networkNotFoundForNode = True |
| 219 | for referrer in referrersForNode: |
| 220 | if referrer.getType() is dummy_relation.getType(): |
| 221 | if referrer.get('type') in ['network'] and referrer.get('network') in ['rcn']: |
| 222 | networkNotFoundForNode = False |
| 223 | break |
| 224 | if networkNotFoundForNode: |
| 225 | # node is not assigned to a network yet |
| 226 | Main.main.getCurrentDataSet().setSelected(endnode) |
| 227 | AutoScaleAction.zoomToSelection() |
| 228 | selectedNode = mv.editLayer.data.getSelected() |
| 229 | if 'downloadReferrersForNodes' in sideEffects: |
| 230 | print "Downloading referrers for ", endnode.get('rcn_ref'), ' ', wayNodes |
| 231 | DownloadReferrersAction.downloadReferrers(mv.editLayer, wayNodes) |
| 232 | else: |
| 233 | print "Would download referrers for ", endnode.get('rcn_ref'), ' ', wayNodes |
| 234 | referrersForNode = endnode.getReferrers() |
| 235 | for referrer in referrersForNode: |
| 236 | if referrer.getType() is dummy_relation.getType(): |
| 237 | networkOrRouteType = referrer.get('type') in ['network'] #, 'route'] |
| 238 | if referrer.get('network')=='rcn' and networkOrRouteType: |
| 239 | relname=referrer.get('name') |
| 240 | if relname: |
| 241 | route_relation_names.append(relname) |
| 242 | elif not(referrer.get('type') in ['route']): |
| 243 | route_relation_names.append('Node not assigned to network yet') |
| 244 | # FIXME This is still buggy |
| 245 | # build 2 structures to help check for continuity on ways |
| 246 | if i==0: |
| 247 | lastNodesBeforeSplit = [wayNodes] |
| 248 | if role and role in ['forward', 'backward']: |
| 249 | if not(branch): |
| 250 | print 'wayNodes', wayNodes |
| 251 | |
| 252 | if wayNodes: |
| 253 | if role in ['forward']: |
| 254 | lastNodesBeforeSplit = [wayNodes[0]] |
| 255 | else: |
| 256 | lastNodesBeforeSplit = [wayNodes[-1]] |
| 257 | else: |
| 258 | return '', True, '|align="right" | way has no nodes||align="right" | {{BrowseRoute|' + str(route.getId()) + '}}||align="right" needs to be downloaded first\n' |
| 259 | if logVerbosity > 29: |
| 260 | print 'lastNodesBeforeSplit', lastNodesBeforeSplit |
| 261 | print way.getNodesCount(), 'startnode', wayNodes[0], 'endnode', wayNodes[-1] |
| 262 | print 'roundabout', roundabout |
| 263 | print wayNodes[-1].get('rcn_ref'),not(member.getUniqueId() == routeMembers[-1].getUniqueId()) |
| 264 | if role in ['forward'] and (wayNodes[-1] in lastNodesBeforeSplit or wayNodes[-1] in roundabout): |
| 265 | branch = 'HigherToLower' |
| 266 | elif role in ['backward'] and wayNodes[0] in lastNodesBeforeSplit: |
| 267 | branch = 'HigherToLower' |
| 268 | |
| 269 | elif not(allWaysgoingFromHigherToLower) and wayNodes[-1].get('rcn_ref') and not(member.getUniqueId() == routeMembers[-1].getUniqueId()): |
| 270 | # 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 |
| 271 | branch = 'HigherToLower' |
| 272 | elif not(branch == 'HigherToLower'): |
| 273 | branch = 'LowerToHigher' |
| 274 | print branch |
| 275 | if branch == 'LowerToHigher': |
| 276 | allWaysgoingFromLowerToHigher.append(member) |
| 277 | elif branch == 'HigherToLower': |
| 278 | allWaysgoingFromHigherToLower.append(member) |
| 279 | else: |
| 280 | branch = None; roundabout = [] |
| 281 | allWaysgoingFromLowerToHigher.append(member) |
| 282 | allWaysgoingFromHigherToLower.append(member) |
| 283 | if way.get('junction') == 'roundabout': |
| 284 | roundabout = way.getNodes() |
| 285 | i+=1 |
| 286 | #if modified: |
| 287 | #commandsList.append(Command.ChangeCommand(route, newRelation)) |
| 288 | #Main.main.undoRedo.add(Command.SequenceCommand("Removing way which has no nodes", commandsList)) |
| 289 | #commandsList = [] |
| 290 | |
| 291 | continuous_forward = True; continuous_backward = True |
| 292 | if len(allWaysgoingFromLowerToHigher) > 1: |
| 293 | continuous_forward = checkForContinuity(allWaysgoingFromLowerToHigher) |
| 294 | if not(continuous_forward) and not(fixme) and 'sortRouteRelations' in sideEffects: |
| 295 | sortedRelation = sortRouteRelation(route, nodesForSorting, beginAndEndNodes) |
| 296 | |
| 297 | if logVerbosity>49: |
| 298 | print route |
| 299 | print sortedRelation |
| 300 | commandsList.append(Command.ChangeCommand(route, sortedRelation)) |
| 301 | Main.main.undoRedo.add(Command.SequenceCommand("Sorted route relation", commandsList)) |
| 302 | allWaysgoingFromLowerToHigher = []; allWaysgoingFromHigherToLower = [] |
| 303 | |
| 304 | routeMembers = route.getMembers(); i=0 |
| 305 | for member in routeMembers: |
| 306 | if member.isWay(): |
| 307 | role = member.getRole() |
| 308 | if i==0: |
| 309 | lastNodesBeforeSplit = [wayNodes] |
| 310 | if role and role in ['forward', 'backward']: |
| 311 | if not(branch): |
| 312 | if role in ['forward']: |
| 313 | lastNodesBeforeSplit = [wayNodes[0]] |
| 314 | else: |
| 315 | lastNodesBeforeSplit = [wayNodes[-1]] |
| 316 | if logVerbosity > 29: |
| 317 | print 'wayNodes', wayNodes |
| 318 | print 'lastNodesBeforeSplit', lastNodesBeforeSplit |
| 319 | print way.getNodesCount(), 'startnode', wayNodes[0], 'endnode', wayNodes[-1] |
| 320 | print 'roundabout', roundabout |
| 321 | |
| 322 | if role in ['forward'] and (wayNodes[-1] in lastNodesBeforeSplit or wayNodes[-1] in roundabout): |
| 323 | branch = 'HigherToLower' |
| 324 | elif role in ['backward'] and wayNodes[0] in lastNodesBeforeSplit: |
| 325 | branch = 'HigherToLower' |
| 326 | elif wayNodes[-1].get('rcn_ref') and not(member.getUniqueId() == routeMembers[-1].getUniqueId()): # not(allWaysgoingFromHigherToLower) and ## this last part is probably not necessary anymore |
| 327 | # 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 |
| 328 | branch = 'HigherToLower' |
| 329 | elif not(branch == 'HigherToLower'): |
| 330 | branch = 'LowerToHigher' |
| 331 | print branch |
| 332 | if branch == 'LowerToHigher': |
| 333 | allWaysgoingFromLowerToHigher.append(member) |
| 334 | elif branch == 'HigherToLower': |
| 335 | allWaysgoingFromHigherToLower.append(member) |
| 336 | else: |
| 337 | branch = None; roundabout = [] |
| 338 | allWaysgoingFromLowerToHigher.append(member) |
| 339 | allWaysgoingFromHigherToLower.append(member) |
| 340 | if way.get('junction') == 'roundabout': |
| 341 | roundabout = way.getNodes() |
| 342 | i+=1 |
| 343 | continuous_forward = checkForContinuity(allWaysgoingFromLowerToHigher) |
| 344 | #else: |
| 345 | else: |
| 346 | # a route relation with only one way member |
| 347 | continuous_forward = True |
| 348 | if len(allWaysgoingFromHigherToLower) > 1: |
| 349 | continuous_backward = checkForContinuity(reversed(allWaysgoingFromHigherToLower)) |
| 350 | else: |
| 351 | # a route relation with only one way member |
| 352 | continuous_backward = True |
| 353 | |
| 354 | # Drawing conclusions about rcn_refs |
| 355 | if logVerbosity > 39: print rcn_refs |
| 356 | if sameNodeNumberRepeated: |
| 357 | rcn_refs.append(rcn_refs[0]) |
| 358 | newNote = note = repr(rcn_refs) |
| 359 | sortedRelation = route |
| 360 | if len(rcn_refs) > 1: |
| 361 | #newRelation = Relation(route) |
| 362 | relationChanged = False |
| 363 | |
| 364 | if rcn_refs[0] > rcn_refs[1]: |
| 365 | rcn_refs.sort() |
| 366 | if len(memberslist)>1 and 'flipOrderOfMembers' in sideEffects: |
| 367 | for member in reversed(memberslist): |
| 368 | sortedRelation.addMember( sortedRelation.getMembersCount(), member) |
| 369 | sortedRelation.removeMember (0) |
| 370 | commandsList.append(Command.ChangeCommand(route, sortedRelation)) |
| 371 | Main.main.undoRedo.add(Command.SequenceCommand("Flipping order of members", commandsList)) |
| 372 | commandsList = [] |
| 373 | note = route.get('note') |
| 374 | newNote = str(rcn_refs[0]).zfill(2) + '-' + str(rcn_refs[1]).zfill(2) |
| 375 | #print note, newNote |
| 376 | if 'modifyNoteTo_xx-yy' in sideEffects: |
| 377 | if not(note) or note != newNote: |
| 378 | if not(note): note = 'nothing' |
| 379 | newRelation.put('note', newNote) |
| 380 | relationChanged = True |
| 381 | commandsList.append(Command.ChangeCommand(route, newRelation)) |
| 382 | |
| 383 | Main.main.undoRedo.add(Command.SequenceCommand("Changing note from " + note + ' to ' + newNote, commandsList)) |
| 384 | if logVerbosity > 9: print 'Flipping members order for ', note |
| 385 | commandsList = [] |
| 386 | |
| 387 | if len(route_relation_names) > 1 and route_relation_names[0] != route_relation_names[1]: |
| 388 | # print 'This is probably a CONNECTION to another network' |
| 389 | if logVerbosity > 9: print route_relation_names |
| 390 | roleInNetwork = 'connection' |
| 391 | else: |
| 392 | print 'less than 2 end nodes with rcn_ref found' |
| 393 | if fixme and not(continuous_forward or continuous_backward): |
| 394 | if logVerbosity > 1: print 'FIXME flag is INCOMPLETE' |
| 395 | if continuous_forward: |
| 396 | wikiCF = 'align="right" | continuous' |
| 397 | if logVerbosity > 29: print 'route is continous in the forward direction' |
| 398 | else: |
| 399 | wikiCF = 'align="right" style="color:red" | NOT continuous' |
| 400 | if logVerbosity > 9: print 'route ',newNote,' is NOT CONTINUOUS in the forward direction' |
| 401 | if logVerbosity > 49: print allWaysgoingFromLowerToHigher |
| 402 | if continuous_backward: |
| 403 | wikiCB = 'align="right" | continuous' |
| 404 | if logVerbosity > 29: print 'route is continous in the backward direction' |
| 405 | else: |
| 406 | wikiCB = 'align="right" style="color:red" | NOT continuous' |
| 407 | if logVerbosity > 9: print 'route ',newNote,' is NOT CONTINUOUS in the backward direction' |
| 408 | if logVerbosity > 49: print allWaysgoingFromHigherToLower |
| 409 | print |
| 410 | if fixme: |
| 411 | wikiFM = 'style="color:red" | fixme' |
| 412 | else: |
| 413 | wikiFM = ' | ' |
| 414 | if fixme or not(continuous_forward) or not(continuous_backward): |
| 415 | problem = True |
| 416 | else: |
| 417 | problem = False |
| 418 | return roleInNetwork, problem, '|align="right" | ' + note + '||align="right" | {{BrowseRoute|' + str(route.getId()) + '}}||align="right" ' + wikiFM + ' ||' + wikiCF + ' ||' + wikiCB + '\n' |
| 419 | |
| 420 | def checkNetwork(network): |
| 421 | name = network.get('name') |
| 422 | if logVerbosity>19: |
| 423 | print '********************************************' |
| 424 | print name |
| 425 | print '********************************************' |
| 426 | if 'createWikiReport' in sideEffects: |
| 427 | wikiReportOnNodes = ('{| class="wikitable" align="left" style="margin:0 0 2em 2em;"\n|-\n|+' + name + |
| 428 | '\n|-\n!style="width:2.5em" | Node\n!Link\n! # Roads\n! # Relations\n|-\n') |
| 429 | wikiReportOnRelations = ('{| class="wikitable" align="left" style="margin:0 0 2em 2em;"\n|-\n|+' + name + |
| 430 | '\n|-\n!style="width:2.5em" | note\n!link\n!fixme\n! forward\n! backward\n|-\n') |
| 431 | i=1 |
| 432 | for networkMember in network.getMembers(): |
| 433 | if networkMember.isRelation(): |
| 434 | routeRelation = networkMember.getRelation() |
| 435 | if routeRelation.hasIncompleteMembers(): |
| 436 | if 'downloadIncompleteMembers' in sideEffects: |
| 437 | print 'Downloading incomplete members for', routeRelation.get('note') |
| 438 | DownloadRelationMemberTask.run(DownloadRelationMemberTask(routeRelation, routeRelation.getIncompleteMembers(), mv.editLayer )) |
| 439 | continue |
| 440 | else: |
| 441 | JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete member of the route relations first') |
| 442 | break |
| 443 | roleFromRouteCheck, problemReported, wikiReport = checkRCNroute(routeRelation) |
| 444 | if problemReported and 'createWikiReport' in sideEffects: |
| 445 | wikiReportOnRelations += wikiReport + '\n|-\n' |
| 446 | role = networkMember.getRole() |
| 447 | if logVerbosity > 29 and role != roleFromRouteCheck: |
| 448 | print |
| 449 | print 'Role in network is ', role |
| 450 | print 'Maybe this should be: ', roleFromRouteCheck |
| 451 | if networkMember.isNode(): |
| 452 | node = networkMember.getNode() |
| 453 | rcn_ref = node.get('rcn_ref') |
| 454 | expected_rcn_route_relations = node.get('expected_rcn_route_relations') |
| 455 | if expected_rcn_route_relations: |
| 456 | expected_rcn_route_relations = int(expected_rcn_route_relations) |
| 457 | else: |
| 458 | expected_rcn_route_relations = 3 |
| 459 | if rcn_ref: |
| 460 | if logVerbosity > 39: print rcn_ref |
| 461 | referrersForNode = node.getReferrers() |
| 462 | networkNotFoundForNode = True |
| 463 | for referrer in referrersForNode: |
| 464 | if referrer.getType() is dummy_relation.getType(): |
| 465 | if referrer.get('type') in ['network'] and referrer.get('network') in ['rcn']: |
| 466 | networkNotFoundForNode = False |
| 467 | break |
| 468 | if networkNotFoundForNode and 'downloadReferrersNodes' in sideEffects: |
| 469 | Main.main.getCurrentDataSet().setSelected(node) |
| 470 | AutoScaleAction.zoomToSelection() |
| 471 | selectedNode = mv.editLayer.data.getSelected() |
| 472 | print 'Downloading referrers for ', selectedNode.get('rcn_ref') |
| 473 | DownloadReferrersAction.downloadReferrers(mv.editLayer, selectedNode) |
| 474 | referrersForNode = node.getReferrers() |
| 475 | |
| 476 | rcnNetworkCountForNode = roads = 0 |
| 477 | for referrer in referrersForNode: |
| 478 | if referrer.getType() is dummy_way.getType(): |
| 479 | if referrer.get('highway'): roads += 1 |
| 480 | referrersForWay = referrer.getReferrers() |
| 481 | if len(referrersForWay) < 1 and 'downloadReferrersForWays' in sideEffects: |
| 482 | Main.main.getCurrentDataSet().setSelected(referrer) |
| 483 | AutoScaleAction.zoomToSelection() |
| 484 | selectedWay = mv.editLayer.data.getSelected() |
| 485 | print 'Downloading referrers for ', referrer.get('name') , ' ', rcn_ref |
| 486 | DownloadReferrersAction.downloadReferrers(mv.editLayer, selectedWay) |
| 487 | referrersForWay = referrer.getReferrers() |
| 488 | for wayReferrer in referrersForWay: |
| 489 | if wayReferrer.getType() is dummy_relation.getType(): |
| 490 | aRelation = wayReferrer |
| 491 | if aRelation.get('type') == 'route' and aRelation.get('network') == 'rcn': |
| 492 | rcnNetworkCountForNode+=1 |
| 493 | networkMembersList = [] |
| 494 | for subMember in network.getMembers(): |
| 495 | if subMember.isRelation(): |
| 496 | routeRelation = subMember.getRelation() |
| 497 | networkMembersList.append(routeRelation.getUniqueId()) |
| 498 | routeId = aRelation.getUniqueId() |
| 499 | if not(routeId in networkMembersList): |
| 500 | if aRelation.get('network') == 'rcn': |
| 501 | roleFromRouteCheck, problemReported, wikiReport = checkRCNroute(aRelation) |
| 502 | if problemReported and 'createWikiReport' in sideEffects: |
| 503 | wikiReportOnRelations += wikiReport + '\n|-\n' |
| 504 | if 'addRouteToNetwork' in sideEffects: |
| 505 | newRelation = Relation(network) |
| 506 | newmember = RelationMember(roleFromRouteCheck, aRelation) |
| 507 | if logVerbosity > 9: print newRelation.getMembersCount(), ' ',i, ' ', newmember |
| 508 | newRelation.addMember( i, newmember) |
| 509 | commandsList = [] |
| 510 | commandsList.append(Command.ChangeCommand(network, newRelation)) |
| 511 | note = aRelation.get('note') |
| 512 | if not(note): |
| 513 | note = '' |
| 514 | Main.main.undoRedo.add(Command.SequenceCommand("Adding " + note + " to network", commandsList)) |
| 515 | commandsList = [] |
| 516 | if logVerbosity > 9: print 'Added newly found RCN route relation to network: ', note |
| 517 | i+=1 |
| 518 | if rcnNetworkCountForNode < expected_rcn_route_relations: |
| 519 | if logVerbosity > 9: print 'Node ', rcn_ref, ' only has ', rcnNetworkCountForNode, ' rcn routes connected to it' |
| 520 | 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' |
| 521 | |
| 522 | i+=1 |
| 523 | if logVerbosity > 19: print |
| 524 | if 'createWikiReport' in sideEffects: |
| 525 | wikiReportOnNodes += ('|-\n|}\n') |
| 526 | wikiReportOnRelations += ('|-\n|}\n<br style="clear:left;" />\n') |
| 527 | fh = open('C:/wikiReport.txt', 'a') |
| 528 | fh.write(wikiReportOnNodes) |
| 529 | fh.write(wikiReportOnRelations) |
| 530 | fh.close() |
| 531 | |
| 532 | |
| 533 | dummy_way = Way() |
| 534 | dummy_relation = Relation() |
| 535 | |
| 536 | mv = getMapView() |
| 537 | if mv and mv.editLayer and mv.editLayer.data: |
| 538 | if 'createWikiReport' in sideEffects: |
| 539 | fh = open('C:/wikiReport.txt', 'w') |
| 540 | fh.close() |
| 541 | selectedRelations = mv.editLayer.data.getSelectedRelations() |
| 542 | |
| 543 | if not(selectedRelations): |
| 544 | JOptionPane.showMessageDialog(Main.parent, "Please select a route, network or collection relation") |
| 545 | else: |
| 546 | for relation in selectedRelations: |
| 547 | if logVerbosity> 49: print relation |
| 548 | if relation.hasIncompleteMembers(): |
| 549 | if 'downloadIncompleteMembers' in sideEffects: |
| 550 | print 'Downloading referrers for ', str(relation.get('name')), ' ', str(relation.get('note')) |
| 551 | DownloadRelationMemberTask.run(DownloadRelationMemberTask(relation, relation.getIncompleteMembers(), mv.editLayer )) |
| 552 | continue |
| 553 | else: |
| 554 | JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete member of the relations first') |
| 555 | break |
| 556 | if relation.get('network') == 'rcn': |
| 557 | relationType = relation.get('type') |
| 558 | if relationType == 'route': |
| 559 | checkRCNroute(relation) |
| 560 | elif relationType == 'network': |
| 561 | checkNetwork(relation) |
| 562 | elif relationType == 'collection': |
| 563 | for collectionMember in relation.getMembers(): |
| 564 | if collectionMember.isRelation(): |
| 565 | networkRelation = collectionMember.getRelation() |
| 566 | if networkRelation.hasIncompleteMembers(): |
| 567 | if 'downloadIncompleteMembers' in sideEffects: |
| 568 | print 'Downloading referrers for ', relation.get('name') |
| 569 | DownloadRelationMemberTask.run(DownloadRelationMemberTask(networkRelation, networkRelation.getIncompleteMembers(), mv.editLayer )) |
| 570 | continue |
| 571 | else: |
| 572 | JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete member of the network relations first') |
| 573 | break |
| 574 | checkNetwork(networkRelation) |
| 575 | |
| 576 | }}} |