def test_insert_decreasing(self): road = CvtdRoad() road.points.append(CvtdRoadPoint(123, 160)) road.points.append(CvtdRoadPoint(124, 120)) road.points.append(CvtdRoadPoint(125, 85)) road.insert(CvtdRoadPoint(1, 290)) self.assertEqual(4, len(road.points)) self.assertEqual(road.points[0].addr, 290) self.assertEqual(road.points[1].addr, 160) self.assertEqual(road.points[2].addr, 120) self.assertEqual(road.points[3].addr, 85) road.insert(CvtdRoadPoint(1, 145)) self.assertEqual(5, len(road.points)) self.assertEqual(road.points[0].addr, 290) self.assertEqual(road.points[1].addr, 160) self.assertEqual(road.points[2].addr, 145) self.assertEqual(road.points[3].addr, 120) self.assertEqual(road.points[4].addr, 85) road.insert(CvtdRoadPoint(1, 45)) self.assertEqual(6, len(road.points)) self.assertEqual(road.points[0].addr, 290) self.assertEqual(road.points[1].addr, 160) self.assertEqual(road.points[2].addr, 145) self.assertEqual(road.points[3].addr, 120) self.assertEqual(road.points[4].addr, 85) self.assertEqual(road.points[5].addr, 45)
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