def test_nonintersecting_roads(self): myMap = CvtdMap() myMap.nodeDict[0] = (CvtdNode(1, 1)) myMap.nodeDict[1] = (CvtdNode(2, 1)) myMap.nodeDict[2] = (CvtdNode(1, 4)) myMap.nodeDict[3] = (CvtdNode(2, 6)) myMap.nodeDict[4] = (CvtdNode(2, 9)) myMap.nodeDict[5] = (CvtdNode(3, 3)) myMap.nodeDict[6] = (CvtdNode(4, 6)) thisRoad = CvtdRoad() thisRoad.name = "Road from 1,1 to 2,9" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(0, 0)) thisRoad.points.append(CvtdRoadPoint(2, 60)) thisRoad.points.append(CvtdRoadPoint(3, 90)) thisRoad.points.append(CvtdRoadPoint(4, 100)) myMap.roadList.append(thisRoad) thisRoad = CvtdRoad() thisRoad.name = "Road from 2,1 to 4,6" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(1, 0)) thisRoad.points.append(CvtdRoadPoint(5, 60)) thisRoad.points.append(CvtdRoadPoint(6, 100)) myMap.roadList.append(thisRoad) intersections = myMap.find_intersecting_roads(0, 0) self.assertEqual(0, len(intersections))
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 read_roads(self, filename): self.nodeDict = {} self.roadList = [] editor = "" this_road = CvtdRoad() try: with open(filename, 'r') as f: for road in f: if road.strip() == "NODE_LIST = [": editor = "NODE_LIST" elif road.strip() == "ROAD_LIST = [": editor = "ROAD_LIST" elif editor == "NODE_LIST" and len( road.strip().split(',')) == 4: lat = float( road.split(',')[0].strip().replace('[', '')) lon = float( road.split(',')[1].strip().replace(']', '')) key = int(road.split(',')[2].strip().replace(']', '')) self.nodeDict[key] = CvtdNode(lat, lon) elif editor == "ROAD_LIST" and len( road.strip().split('",')) == 3: this_road = CvtdRoad() this_road.name = road.split('",')[0].replace( '[', '').replace('"', '').strip() this_road.dir = road.split('",')[1].replace( '"', '').strip() points = road.split('",')[2].split('], [') points = [ p.replace('[', '').replace(']', '').replace(',\n', '').strip() for p in points ] this_road.points = [ CvtdRoadPoint(int(node), int(addr)) for node, addr in [x.split(', ') for x in points] ] self.roadList.append(this_road) print("Read successful, read {} nodes and {} roads".format( len(self.nodeDict), len(self.roadList))) except FileNotFoundError: print("Error: File \"{}\" does not exist".format(filename))
def test_multipoint_intersecting_roads(self): myMap = CvtdMap() myMap.nodeDict[0] = (CvtdNode(1, 1)) myMap.nodeDict[1] = (CvtdNode(1, 3)) myMap.nodeDict[2] = (CvtdNode(1, 5)) myMap.nodeDict[3] = (CvtdNode(3, 1)) myMap.nodeDict[4] = (CvtdNode(3, 3)) myMap.nodeDict[5] = (CvtdNode(3, 5)) myMap.nodeDict[6] = (CvtdNode(2, 2)) myMap.nodeDict[7] = (CvtdNode(2, 4)) myMap.nodeDict[8] = (CvtdNode(4, 4)) myMap.nodeDict[9] = (CvtdNode(4, 2)) thisRoad = CvtdRoad() thisRoad.name = "Road from 1,1 to 3,5" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(0, 0)) thisRoad.points.append(CvtdRoadPoint(1, 10)) thisRoad.points.append(CvtdRoadPoint(2, 20)) thisRoad.points.append(CvtdRoadPoint(3, 30)) thisRoad.points.append(CvtdRoadPoint(4, 40)) thisRoad.points.append(CvtdRoadPoint(5, 50)) myMap.roadList.append(thisRoad) thisRoad = CvtdRoad() thisRoad.name = "Road from 2,2 to 4,4" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(6, 0)) thisRoad.points.append(CvtdRoadPoint(7, 10)) thisRoad.points.append(CvtdRoadPoint(8, 20)) thisRoad.points.append(CvtdRoadPoint(9, 30)) myMap.roadList.append(thisRoad) intersections = myMap.find_intersecting_roads(0, 0) self.assertEqual(2, len(intersections))
def import_xml_file(self, filename): print("Importing file " + filename) tree = ET.parse(filename) root = tree.getroot() # Load all the nodes, using an extra components "tags" for node in root.iter('node'): this_node = CvtdNode(float(node.attrib['lat']), float(node.attrib['lon'])) this_node.tags = {} this_node.attrib = node.attrib tag_keys = [t.attrib['k'] for t in node.iter('tag')] tag_vals = [t.attrib['v'] for t in node.iter('tag')] for ix, key in enumerate(tag_keys): this_node.tags[key] = tag_vals[ix] try: self.nodeDict[int(this_node.attrib['id'])] = this_node except KeyError: print("Fatal Error: Node did not have an ID field") return # Load all the ways, using an extra components "tags" for way in root.iter('way'): this_way = CvtdRoad() this_way.tags = {} this_way.attrib = way.attrib for nd in way.iter('nd'): p = CvtdRoadPoint(int(nd.attrib['ref']), None) this_way.points.append(p) tag_keys = [t.attrib['k'] for t in way.iter('tag')] tag_vals = [t.attrib['v'] for t in way.iter('tag')] for ix, key in enumerate(tag_keys): this_way.tags[key] = tag_vals[ix] if key == "name": this_way.name = tag_vals[ix] self.roadList.append(this_way)
def test_find_intersecting_roads(self): myMap = CvtdMap() myMap.nodeDict[0] = (CvtdNode(1, 1)) myMap.nodeDict[1] = (CvtdNode(4, 4)) myMap.nodeDict[2] = (CvtdNode(1, 4)) myMap.nodeDict[3] = (CvtdNode(4, 1)) myMap.nodeDict[4] = (CvtdNode(3, 4)) myMap.nodeDict[5] = (CvtdNode(4, 3)) thisRoad = CvtdRoad() thisRoad.name = "Road from 1,1 to 4,4" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(0, 0)) thisRoad.points.append(CvtdRoadPoint(1, 60)) myMap.roadList.append(thisRoad) thisRoad = CvtdRoad() thisRoad.name = "Road from 1,4 to 4,1" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(2, 0)) thisRoad.points.append(CvtdRoadPoint(3, 60)) myMap.roadList.append(thisRoad) thisRoad = CvtdRoad() thisRoad.name = "Road from 3,4 to 4,3" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(4, 0)) thisRoad.points.append(CvtdRoadPoint(5, 50)) myMap.roadList.append(thisRoad) intersections = myMap.find_intersecting_roads(0, 0) self.assertEqual(2, len(intersections)) self.assertEqual(0, intersections[0][0].roadIx) self.assertEqual(30, intersections[0][0].addr) self.assertEqual(1, intersections[0][1].roadIx) self.assertEqual(30, intersections[0][1].addr) self.assertEqual(0, intersections[1][0].roadIx) self.assertEqual(50, intersections[1][0].addr) self.assertEqual(2, intersections[1][1].roadIx) self.assertEqual(25, intersections[1][1].addr)
def test_read_write_roads(self): myMap = CvtdMap() myMap.nodeDict[0] = (CvtdNode(1, 1)) myMap.nodeDict[1] = (CvtdNode(4, 4)) myMap.nodeDict[2] = (CvtdNode(1, 4)) myMap.nodeDict[3] = (CvtdNode(4, 1)) myMap.nodeDict[4] = (CvtdNode(3, 4)) myMap.nodeDict[5] = (CvtdNode(4, 3)) thisRoad = CvtdRoad() thisRoad.name = "Road from 0 to 60" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(0, 0)) thisRoad.points.append(CvtdRoadPoint(1, 30)) thisRoad.points.append(CvtdRoadPoint(2, 60)) myMap.roadList.append(thisRoad) thisRoad = CvtdRoad() thisRoad.name = "Road from 0 to 60" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(1, 0)) thisRoad.points.append(CvtdRoadPoint(3, 30)) thisRoad.points.append(CvtdRoadPoint(4, 50)) thisRoad.points.append(CvtdRoadPoint(5, 60)) myMap.roadList.append(thisRoad) thisRoad = CvtdRoad() thisRoad.name = "Road from 0 to 50" thisRoad.dir = "Up" thisRoad.points.append(CvtdRoadPoint(0, 0)) thisRoad.points.append(CvtdRoadPoint(5, 50)) myMap.roadList.append(thisRoad) myMap.write_roads("tmp_roads.txt") myCmpMap = CvtdMap() myCmpMap.read_roads("tmp_roads.txt") self.assertEqual(len(myMap.nodeDict), len(myCmpMap.nodeDict)) self.assertEqual(len(myMap.roadList), len(myCmpMap.roadList)) self.assertEqual(myMap.nodeDict[0].lat, myCmpMap.nodeDict[0].lat) self.assertEqual(myMap.nodeDict[0].lon, myCmpMap.nodeDict[0].lon) self.assertEqual(myMap.nodeDict[1].lat, myCmpMap.nodeDict[1].lat) self.assertEqual(myMap.nodeDict[1].lon, myCmpMap.nodeDict[1].lon) self.assertEqual(myMap.nodeDict[2].lat, myCmpMap.nodeDict[2].lat) self.assertEqual(myMap.nodeDict[2].lon, myCmpMap.nodeDict[2].lon) self.assertEqual(myMap.nodeDict[3].lat, myCmpMap.nodeDict[3].lat) self.assertEqual(myMap.nodeDict[3].lon, myCmpMap.nodeDict[3].lon) self.assertEqual(myMap.nodeDict[4].lat, myCmpMap.nodeDict[4].lat) self.assertEqual(myMap.nodeDict[4].lon, myCmpMap.nodeDict[4].lon) self.assertEqual(myMap.nodeDict[5].lat, myCmpMap.nodeDict[5].lat) self.assertEqual(myMap.nodeDict[5].lon, myCmpMap.nodeDict[5].lon) self.assertEqual(myMap.roadList[0].name, myCmpMap.roadList[0].name) self.assertEqual(myMap.roadList[0].dir, myCmpMap.roadList[0].dir) self.assertEqual(myMap.roadList[0].points[0].node, myCmpMap.roadList[0].points[0].node) self.assertEqual(myMap.roadList[0].points[0].addr, myCmpMap.roadList[0].points[0].addr) self.assertEqual(myMap.roadList[0].points[1].node, myCmpMap.roadList[0].points[1].node) self.assertEqual(myMap.roadList[0].points[1].addr, myCmpMap.roadList[0].points[1].addr) self.assertEqual(myMap.roadList[0].points[2].node, myCmpMap.roadList[0].points[2].node) self.assertEqual(myMap.roadList[0].points[2].addr, myCmpMap.roadList[0].points[2].addr) self.assertEqual(myMap.roadList[1].name, myCmpMap.roadList[1].name) self.assertEqual(myMap.roadList[1].dir, myCmpMap.roadList[1].dir) self.assertEqual(myMap.roadList[1].points[0].node, myCmpMap.roadList[1].points[0].node) self.assertEqual(myMap.roadList[1].points[0].addr, myCmpMap.roadList[1].points[0].addr) self.assertEqual(myMap.roadList[1].points[1].node, myCmpMap.roadList[1].points[1].node) self.assertEqual(myMap.roadList[1].points[1].addr, myCmpMap.roadList[1].points[1].addr) self.assertEqual(myMap.roadList[1].points[2].node, myCmpMap.roadList[1].points[2].node) self.assertEqual(myMap.roadList[1].points[2].addr, myCmpMap.roadList[1].points[2].addr) self.assertEqual(myMap.roadList[1].points[3].node, myCmpMap.roadList[1].points[3].node) self.assertEqual(myMap.roadList[1].points[3].addr, myCmpMap.roadList[1].points[3].addr) self.assertEqual(myMap.roadList[2].name, myCmpMap.roadList[2].name) self.assertEqual(myMap.roadList[2].dir, myCmpMap.roadList[2].dir) self.assertEqual(myMap.roadList[2].points[0].node, myCmpMap.roadList[2].points[0].node) self.assertEqual(myMap.roadList[2].points[0].addr, myCmpMap.roadList[2].points[0].addr) self.assertEqual(myMap.roadList[2].points[1].node, myCmpMap.roadList[2].points[1].node) self.assertEqual(myMap.roadList[2].points[1].addr, myCmpMap.roadList[2].points[1].addr) os.remove("tmp_roads.txt")
def define_road_details(): this_road = CvtdRoad() this_road.name = input('Street name: ') this_road.dir = input('Direction (most likely "N/S" or "E/W"): ') return this_road
def test_compare_road(self): nodeDict = {} nodeDict[1] = CvtdNode(1, 1) nodeDict[2] = CvtdNode(2, 2) nodeDict[3] = CvtdNode(3, 3) nodeDict[4] = CvtdNode(4, 4) nodeDict[5] = CvtdNode(5, 5) nodeDict[6] = CvtdNode(6, 6) nodeDict[7] = CvtdNode(7, 7) nodeDict[8] = CvtdNode(8, 8) nodeDict[9] = CvtdNode(9, 9) road1 = CvtdRoad() road1.name = "Road A" road1.dir = "Up" road1.points.append(CvtdRoadPoint(1, 1)) road1.points.append(CvtdRoadPoint(2, 2)) road1.points.append(CvtdRoadPoint(3, 3)) road1.points.append(CvtdRoadPoint(4, 4)) road1.points.append(CvtdRoadPoint(5, 5)) road2 = CvtdRoad() road2.name = "Road B" road2.dir = "Up" road2.points.append(CvtdRoadPoint(3, 3)) road2.points.append(CvtdRoadPoint(4, 4)) road2.points.append(CvtdRoadPoint(5, 5)) road2.points.append(CvtdRoadPoint(6, 6)) road2.points.append(CvtdRoadPoint(7, 7)) road3 = CvtdRoad() road3.name = "Road C" road3.dir = "Up" road3.points.append(CvtdRoadPoint(4, 4)) road3.points.append(CvtdRoadPoint(5, 5)) road3.points.append(CvtdRoadPoint(6, 6)) road4 = CvtdRoad() road4.name = "Road D" road4.dir = "Up" road4.points.append(CvtdRoadPoint(9, 9)) road4.points.append(CvtdRoadPoint(8, 8)) road4.points.append(CvtdRoadPoint(7, 7)) road5 = CvtdRoad() road5.name = "Road E" road5.dir = "Up" road5.points.append(CvtdRoadPoint(4, 4)) road5.points.append(CvtdRoadPoint(7, 7)) import pdb pdb.set_trace() self.assertEqual(0, road1.compare_road(nodeDict, road1, nodeDict)) self.assertEqual(4, road1.compare_road(nodeDict, road2, nodeDict)) self.assertEqual(4, road1.compare_road(nodeDict, road3, nodeDict)) self.assertEqual(-1, road1.compare_road(nodeDict, road4, nodeDict)) self.assertEqual(3, road1.compare_road(nodeDict, road5, nodeDict)) self.assertEqual(4, road2.compare_road(nodeDict, road1, nodeDict)) self.assertEqual(0, road2.compare_road(nodeDict, road2, nodeDict)) self.assertEqual(1, road2.compare_road(nodeDict, road3, nodeDict)) self.assertEqual(4, road2.compare_road(nodeDict, road4, nodeDict)) self.assertEqual(3, road2.compare_road(nodeDict, road5, nodeDict)) self.assertEqual(4, road3.compare_road(nodeDict, road1, nodeDict)) self.assertEqual(2, road3.compare_road(nodeDict, road2, nodeDict)) self.assertEqual(0, road3.compare_road(nodeDict, road3, nodeDict)) self.assertEqual(-1, road3.compare_road(nodeDict, road4, nodeDict)) self.assertEqual(4, road3.compare_road(nodeDict, road5, nodeDict)) self.assertEqual(-1, road4.compare_road(nodeDict, road1, nodeDict)) self.assertEqual(4, road4.compare_road(nodeDict, road2, nodeDict)) self.assertEqual(-1, road4.compare_road(nodeDict, road3, nodeDict)) self.assertEqual(0, road4.compare_road(nodeDict, road4, nodeDict)) self.assertEqual(4, road4.compare_road(nodeDict, road5, nodeDict)) self.assertEqual(3, road5.compare_road(nodeDict, road1, nodeDict)) self.assertEqual(3, road5.compare_road(nodeDict, road2, nodeDict)) self.assertEqual(4, road5.compare_road(nodeDict, road3, nodeDict)) self.assertEqual(4, road5.compare_road(nodeDict, road4, nodeDict)) self.assertEqual(0, road5.compare_road(nodeDict, road5, nodeDict))
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