def edit(self, nodeDict): while True: print("n: Name: " + self.name) print("d: Direction: " + self.dir) for pointIx, point in enumerate(self.points): print( f"{pointIx+1}: {point.addr} at {nodeDict[point.node].lat}, {nodeDict[point.node].lon}" ) action = CvtdUtil.input_int( f"What do you want to edit or delete? Enter 'q' when done: ", 1, len(self.points), validAnswers=['q', 'n', 'd']) if type(action) is int: realPointIx = action - 1 pointAction = CvtdUtil.input_int( f"Choose one of the following: (1) edit addr, (2) edit node, (3) delete point: ", 1, 3) if pointAction == 1: # If we have more than one point, increasing/decreasing is defined and we can maintain the constraint # Else, we just need to set neAddr to the current if len(self.points) > 1: if self.increasing: minAddr = self.points[ realPointIx - 1].addr + 1 if realPointIx > 0 else None maxAddr = self.points[ realPointIx + 1].addr - 1 if realPointIx < ( len(self.points) - 1) else None else: maxAddr = self.points[ realPointIx - 1].addr - 1 if realPointIx > 0 else None minAddr = self.points[ realPointIx + 1].addr + 1 if realPointIx < ( len(self.points) - 1) else None else: minAddr = None maxAddr = None self.points[realPointIx].addr = CvtdUtil.input_int( f"Enter a new address (min {minAddr}, max {maxAddr}): ", minAddr, maxAddr) elif pointAction == 2: print("Not Implemented Error. Sorry") elif pointAction == 3: del self.points[realPointIx] elif action == 'n': self.name = input("Enter name for this road: ") elif action == 'd': self.dir = input( f"Enter a direction for {self.name} ('N/S', 'E/W', or other'): " ) else: break
def search_road(self): search = input("Search for a road with the following text: ") roadIxList = [i for i in range(len(self.roadList)) if search in self.roadList[i].name] ways = [self.roadList[way] for way in roadIxList] # ways = [way for way in self.roadList if search in way.name] if len(roadIxList) == 0: print("No ways found.") return # Print information about each of the matching ways for ix, way in enumerate(ways): try: print(f"[{ix+1}]: {way.name} has {len(way.points)} nodes") print(" " + ", ".join([f"({self.nodeDict[p.node].lat}, {self.nodeDict[p.node].lon})" for p in way.points])) except KeyError: print(f"Unknown node") # Here, compare with what is currently in the file to see if we want to add onto a road, modify a road, or do nothing # For the present, we'll just add a new road whichWay = CvtdUtil.input_int("Adding a new road. Start with which way? ", 1, len(ways)) if type(whichWay) is int: self.add_road(roadIxList[whichWay - 1], None)
def add_road(self, wayIx, baseRoadIx): way = self.roadList[wayIx] addedRoads = [wayIx] newRoad = CvtdRoad() if baseRoadIx is not None: # If we're appending onto a road, add all the nodes from the main map into this map baseRoad = self.mainMap.roadList[baseRoadIx] newRoad.name = baseRoad.name newRoad.dir = baseRoad.dir for point in baseRoad.points: self.nodeDict[point.node] = self.mainMap.nodeDict[point.node] newRoad.points.append(CvtdRoadPoint(point.node, point.addr)) print(f"{way.name} goes from {self.nodeDict[way.points[0].node]} to {self.nodeDict[way.points[-1].node]} with {len(way.points)} points") newName = input(f'Enter a name for this road (leave blank for "{way.name}"): ') if newName: newRoad.name = newName else: newRoad.name = way.name newRoad.dir = input(f"Enter a direction for {newRoad.name} ('N/S', 'E/W', or other): ") minValue = None maxValue = None lastValue = None # Merge check, only once, at the end. Reset to True if they accept the merge mergeCheck = True # For each point in this way pointList = way.points # Let them come back to some points if desired while len(pointList) > 0: returnPointList = [] for point in pointList: # Don't let the same point get added twice if point.node in [p.node for p in newRoad.points]: continue # Store the node in question node = self.nodeDict[point.node] # Look for ways in the OSM file that also use this node newIntersections = [] for checkWay in self.roadList: if point.node in [checkPoint.node for checkPoint in checkWay.points]: newIntersections.append(checkWay) # Calculate the "best guess" for the address at this point interpolateAddress = newRoad.estimate_addr(node, self.nodeDict) print(f"\nNext point is ({node.lat}, {node.lon}), best guess {interpolateAddress}") if len(newIntersections) > 0: print(f"The following {len(newIntersections)} roads from the OSM file intersect at this node: ") for way in newIntersections: print(" - " + way.name + ': ' + str(way.tags)) # Determine a max and a min value for this point if len(newRoad.points) == 0: minValue = None maxValue = None neValue = None elif len(newRoad.points) == 1: minValue = None maxValue = None neValue = newRoad.points[0].addr else: point_ix, proj_ratio, error = newRoad.compute_proj_ratio(node.lat, node.lon, self.nodeDict) inc = newRoad.increasing() if (proj_ratio < 0 and inc) or (proj_ratio > 1 and not inc): # Address must be less than the first address minValue = None maxValue = newRoad.points[0].addr - 1 neValue = None elif (proj_ratio > 1 and inc) or (proj_ratio < 0 and not inc): # Address must be greater than the final address minValue = newRoad.points[-1].addr + 1 maxValue = None neValue = None else: # Address must be between point #point_ix and the following point minValue = newRoad.points[point_ix].addr + 1 if inc else newRoad.points[point_ix + 1].addr - 1 maxValue = newRoad.points[point_ix + 1].addr - 1 if inc else newRoad.points[point_ix].addr + 1 neValue = None # Now let them choose an address, or 'skip' (ignore this point), or 'return' (come back to this point later) repeatThisAddr = True while repeatThisAddr: repeatThisAddr = False addr = CvtdUtil.input_int("Enter the address for this point, or 'skip', 'return' or 'edit': ", minValue, maxValue, neValue, ['skip', 'return', 'edit', 'quit', 's', 'r', 'e', 'q']) if addr is not None: if addr in ["skip", 's']: pass elif addr in ["return", 'r']: returnPointList.append(point) elif addr in ["edit", 'e']: newRoad.edit(self.nodeDict) repeatThisAddr = True elif addr in ["quit", 'q']: return else: newRoad.insert(CvtdRoadPoint(point.node, addr)) newRoad.describe(self.nodeDict) else: return if len(returnPointList) > 0: pointList = returnPointList elif mergeCheck: pointList = [] mergeCheck = False print("\nYou've defined the following road:") newRoad.describe(self.nodeDict) print('') # They successfully added all the points. See if they want to merge with another road possibleMerges = [way for way in self.roadList if newRoad.extendable(way)] if len(possibleMerges) > 0: print(f"There are {len(possibleMerges)} ways that you could merge into this road. ") for ix, way in enumerate(possibleMerges): print(f"[{ix+1}]: {way.name} has {len(way.points)} nodes") print(" " + ", ".join([f"({self.nodeDict[p.node].lat}, {self.nodeDict[p.node].lon})" for p in way.points])) mergeWay = CvtdUtil.input_int(f"Merge another road into this road? (1-{len(possibleMerges)}) or (n)o: ", 1, len(possibleMerges), validAnswers=['n', 'no']) if type(mergeWay) is int: mergeWay = mergeWay - 1 pointList = possibleMerges[mergeWay].points addedRoads.append(self.roadList.index(possibleMerges[mergeWay])) mergeCheck = True else: # They were offered a merge check but they rejected it pointList = [] confirm = 'e' while confirm == 'e': confirm = input("Add this new road to your map? (y/n/[e]dit): ") if confirm == 'e': newRoad.edit(self.nodeDict) print("\nYou've defined the following road:") newRoad.describe(self.nodeDict) print('') elif confirm == 'y': # If we are replacing a street (adding onto one), replace. Else add import pdb; pdb.set_trace() if baseRoadIx is not None: self.mainMap.replace_street_with_nodes(newRoad, self.nodeDict, baseRoadIx) else: self.mainMap.add_street_with_nodes(newRoad, self.nodeDict) print(f"You now have {len(self.mainMap.roadList)} roads.") # Remove each road, adjusting other indices for each road removed for ixOfIx, ixToRemove in enumerate(addedRoads): # Delete the ixToRemove'th index in self.roadList del self.roadList[ixToRemove] # Decrement all successive indices that are greater than ixToRemove for ixOfAdjustIx, ixToAdjust in enumerate(addedRoads[ixOfIx+1:]): if ixToAdjust > ixToRemove: addedRoads[ixOfAdjustIx] = addedRoads[ixOfAdjustIx] - 1 return addedRoads