コード例 #1
0
ファイル: roadtool.py プロジェクト: kenyonsmith/cvtdapp
def search_nodes(map):
  if len(map.nodeList) > 0:
    valid, lat, lon = parse_gps()
    if not valid:
      return
    dlist = map.generate_dlist(lat, lon)
    dlist_sorted = sorted(dlist)
    show_type = input("Show (1) nodes closer than a certain distance, or (2) given number of closest nodes: ")
    show_num = 0
    if show_type == '1':
      keepTrying = 'y'
      while keepTrying == 'y':
        dist_str = input("Show nodes closer than the following distance (in feet): ")
        try:
          dist_num = int(dist_str)
          show_num = sum([CvtdUtil.coord_to_ft(y) < dist_num for y in dlist])
          show = input(f"Show {show_num} entries (y/n): ")
          if show == 'y':
            print(f"Showing {show_num} nodes within {dist_num} feet of {lat}, {lon}")
            for i in range(show_num):
              dlist_ix = dlist.index(dlist_sorted[i])
              e = round(CvtdUtil.coord_to_ft(dlist_sorted[i]), 3)
              print(f"{i+1}: {map.nodeList[dlist_ix].lat}, {map.nodeList[dlist_ix].lon} ({e} feet)")
            keepTrying = 'n'
          else:
            keepTrying = input("Try again (y/n): ")
        except ValueError:
          keepTrying = input(f"Error: Could not convert ${show_str} to an integer. Try again (y/n): ")
    elif show_type == '2':
      nnodes = len(map.nodeList)
      show_str = input(f"Show how many entries (max {nnodes}): ")
      try:
        show_num = min(int(show_str), nnodes)
        print(f"Showing {show_num} nodes close to {lat}, {lon}")
        for i in range(show_num):
          dlist_ix = dlist.index(dlist_sorted[i])
          e = round(dlist_sorted[i]*70*5280, 3)
          print(f"{i+1}: {map.nodeList[dlist_ix].lat}, {map.nodeList[dlist_ix].lon} ({e} feet)")
      except ValueError:
        print(f"Error: Could not convert ${show_str} to an integer")
  
    # Now, let them choose one of these nodes
    if show_num > 0:
      while True:
        try:
          node_info = int(input(f"Get more info about a node (1-{show_num}) or (n)o: "))
          if 1 <= node_info <= show_num:
            plist = map.get_node_usage(dlist.index(dlist_sorted[node_info - 1]))
            if len(plist) > 0:
              print("The following roads use this node: ")
              for p in plist:
                print(p.addr_repr(map.roadList))
          else:
            break
        except ValueError:
          break
  else:
    print("No nodes have been added, you might want to read roads.txt (key 'r')")
コード例 #2
0
ファイル: testCvtdUtil.py プロジェクト: kenyonsmith/cvtdapp
    def test_split_double_quotes(self):
        s = "1,2,3,'Once, upon a time, something happened',6"
        self.assertListEqual([
            "1", "2", "3", "'Once", " upon a time", " something happened'", "6"
        ], CvtdUtil.split_double_quotes(s, ','))

        s2 = '"3,3","4,4","5,5"\n'
        self.assertListEqual(['"3,3"', '"4,4"', '"5,5"\n'],
                             CvtdUtil.split_double_quotes(s2, ','))
コード例 #3
0
ファイル: cvtdRoad.py プロジェクト: kenyonsmith/cvtdapp
    def compute_addr(self, lat, lon, nodeDict):
        point_ix, proj_ratio, error = self.compute_proj_ratio(
            lat, lon, nodeDict)

        vaddr_begin = self.points[point_ix].addr
        vaddr_end = self.points[point_ix + 1].addr

        address = round(proj_ratio * (vaddr_end - vaddr_begin) + vaddr_begin)
        addrRepr = CvtdUtil.addr_repr(address, self.dir, self.name)

        return addrRepr, CvtdUtil.coord_to_ft(error)
コード例 #4
0
ファイル: cvtdRoad.py プロジェクト: kenyonsmith/cvtdapp
 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
コード例 #5
0
def add_to_print_list(myMap, locator, print_list, rid, ix):
    try:
        position = locator.pos[rid][ix]
        t = position.timestamp
        lat = position.lat
        lon = position.lon
        dir = position.direction
    except IndexError:
        return

    # Determine route
    try:
        route = myMap.routeDict[rid]
        routeName = route.routeShortName
        # validStreets = route.get_street_list()
    except KeyError:
        routeName = "Unknown Route"
        # validStreets = None
    validStreets = None

    # Compute address
    # roadIx, addr, error = myMap.compute_addr_repr(lat, lon, validStreets)
    roadIx, addr, error = myMap.compute_addr_repr(lat, lon, None)
    if validStreets is not None and error > 250:
        roadIx, addr_off_route, error_off_route = myMap.compute_addr_repr(
            lat, lon, None)
        if error_off_route < 200:
            addr = "!" + addr_off_route
            error = error_off_route
    error = round(error)

    # Determine if direction is actual or if it should be X
    try:
        lat_to_lat_diff = CvtdUtil.coord_to_ft(
            abs(locator.pos[rid][ix - 1].lat - lat))
        lon_to_lon_diff = CvtdUtil.coord_to_ft(
            abs(locator.pos[rid][ix - 1].lon - lon))
        pos_to_pos_diff = math.sqrt(lat_to_lat_diff**2 + lon_to_lon_diff**2)
        if (pos_to_pos_diff < 40):
            dir = Direction.X
        else:
            dir = direction.get_direction(dir)
    except IndexError:
        dir = direction.get_direction(dir)

    # Add to list to print later
    try:
        print_list[rid].append([t, addr, error, dir])
    except KeyError:
        print_list[rid] = [routeName]
        print_list[rid].append([t, addr, error, dir])
コード例 #6
0
ファイル: gtfsImporter.py プロジェクト: kenyonsmith/cvtdapp
    def import_calendar(dirPath, myMap):
        print("Importing calendar...")
        calendarDict = {}
        calendar = CvtdUtil.parse_csv(dirPath + "/calendar.txt")
        strFormat = '%Y%m%d'
        try:
            for ix, sid in enumerate(calendar['service_id']):
                if sid not in calendarDict:
                    calendarDict[sid] = GtfsCalendarEntry()
                monday = int(calendar['monday'][ix])
                tuesday = int(calendar['tuesday'][ix])
                wednesday = int(calendar['wednesday'][ix])
                thursday = int(calendar['thursday'][ix])
                friday = int(calendar['friday'][ix])
                saturday = int(calendar['saturday'][ix])
                sunday = int(calendar['sunday'][ix])
                calendarDict[sid].generateDaysOfWeek(monday, tuesday,
                                                     wednesday, thursday,
                                                     friday, saturday, sunday)
                calendarDict[sid].startDate = datetime.datetime.strptime(
                    calendar['start_date'][ix], strFormat)
                calendarDict[sid].endDate = datetime.datetime.strptime(
                    calendar['end_date'][ix], strFormat)
        except (KeyError, IndexError, ValueError):
            print(f"Error: import_calendar, ix {ix}, sid {sid}")
            pass

        myMap.calendarDict = calendarDict
コード例 #7
0
ファイル: gtfsImporter.py プロジェクト: kenyonsmith/cvtdapp
    def import_stops(dirPath, myMap):
        print("Importing stops...")
        stopDict = {}
        stops = CvtdUtil.parse_csv(dirPath + "/stops.txt")
        try:
            for ix, sid in enumerate(stops['stop_id']):
                if sid not in stopDict:
                    stopDict[sid] = GtfsStop()

                if stops['stop_code'][ix] is not '':
                    stopDict[sid].stopCode = int(stops['stop_code'][ix])
                stopDict[sid].stopName = stops['stop_name'][ix]
                stopDict[sid].lat = float(stops['stop_lat'][ix])
                stopDict[sid].lon = float(stops['stop_lon'][ix])
                if stops['location_type'][ix] is not '':
                    stopDict[sid].locationType = int(
                        stops['location_type'][ix])
                if stops['parent_station'][ix] is not '':
                    stopDict[sid].parentStation = int(
                        stops['parent_station'][ix])
        except (KeyError, IndexError, ValueError):
            print(f"Error: import_stops, ix {ix}, sid {sid}")
            pass

        myMap.stopDict = stopDict
コード例 #8
0
ファイル: gtfsImporter.py プロジェクト: kenyonsmith/cvtdapp
    def import_shapes(dirPath, myMap):
        print("Importing shapes...")
        shapeDict = {}
        shapes = CvtdUtil.parse_csv(dirPath + "/shapes.txt")
        try:
            for ix, sid in enumerate(shapes['shape_id']):
                if sid not in shapeDict:
                    shapeDict[sid] = GtfsShape()
                lat = float(shapes['shape_pt_lat'][ix])
                lon = float(shapes['shape_pt_lon'][ix])
                shapeDict[sid].pointList.append(CvtdNode(lat, lon))
        except (KeyError, IndexError, ValueError):
            print(f"Error: import_shapes, ix {ix}, sid {sid}")
            pass

        for shapeId in shapeDict:
            for cmpShapeId in shapeDict:
                if shapeId != cmpShapeId:
                    if shapeDict[shapeId].copyOfId is None and shapeDict[
                            cmpShapeId].copyOfId is None:
                        if shapeDict[shapeId].compare_point_list(
                                shapeDict[cmpShapeId].pointList):
                            shapeDict[cmpShapeId].pointList = []
                            shapeDict[cmpShapeId].copyOfId = shapeId
                            print(f"Shape {cmpShapeId} is a copy of {shapeId}")
        myMap.shapeDict = shapeDict
コード例 #9
0
    def find_intersecting_roads(self, road_ix, tol):
        intersections = []

        # Find roads that intersect with each segment individually
        road = self.roadList[road_ix]
        for point_ix, point in enumerate(road.points[:-1]):
            n1s = self.nodeDict[point.node]
            n1e = self.nodeDict[road.points[point_ix + 1].node]

            # Loop through all roads to see if they intersect with this segment
            for check_ix, check_road in enumerate(self.roadList):
                # Don't check to see if a road intersects with itself
                if check_ix != road_ix:
                    for check_point_ix, check_point in enumerate(
                            check_road.points[:-1]):
                        n2s = self.nodeDict[check_point.node]
                        n2e = self.nodeDict[check_road.points[check_point_ix +
                                                              1].node]

                        cross = CvtdUtil.get_line_intersection(
                            n1s, n1e, n2s, n2e)
                        if cross:
                            addr1 = self.compute_addr(cross[0], cross[1],
                                                      [road_ix])[1]
                            addr2 = self.compute_addr(cross[0], cross[1],
                                                      [check_ix])[1]
                            p1 = ContainedRoadPoint(addr1, road_ix)
                            p2 = ContainedRoadPoint(addr2, check_ix)
                            intersections.append([p1, p2])
        return intersections
コード例 #10
0
ファイル: cvtdRoad.py プロジェクト: kenyonsmith/cvtdapp
    def compute_proj_ratio(self, lat, lon, nodeDict):
        min_point_ix = 0
        min_proj_ratio = 0
        min_pos_to_proj = 0x7FFFFFFF

        for point_ix, point in enumerate(self.points[:-1]):
            blon = nodeDict[point.node].lon
            blat = nodeDict[point.node].lat
            elon = nodeDict[self.points[point_ix + 1].node].lon
            elat = nodeDict[self.points[point_ix + 1].node].lat
            street_sc, pos_sc, projection_sc, begin_or_end = CvtdUtil.sub_proj_ratio(
                lat, lon, blat, blon, elat, elon)

            if projection_sc != 0.0:
                proj_sc_fixed = min(projection_sc, street_sc)
                try:
                    pos_to_proj = math.sqrt((pos_sc * pos_sc) -
                                            (proj_sc_fixed * proj_sc_fixed))
                except ValueError:
                    pos_to_proj = 0

                if pos_to_proj < min_pos_to_proj:
                    min_point_ix = point_ix
                    min_proj_ratio = projection_sc / street_sc
                    min_pos_to_proj = pos_to_proj

                    if begin_or_end == 0:
                        min_proj_ratio = 1 - min_proj_ratio
            else:
                print(
                    f"Error [compute_proj_ratio] on road called {self.name}: two adjacent points with same node"
                )

        return min_point_ix, min_proj_ratio, min_pos_to_proj
コード例 #11
0
ファイル: roadtool.py プロジェクト: kenyonsmith/cvtdapp
def choose_gps(map):
  valid, lat, lon = parse_gps()
  if not valid:
    return False
  node_ix = len(map.nodeList)
  dlist = map.generate_dlist(lat, lon)
  dlist_sorted = sorted(dlist)
  node_count = sum([CvtdUtil.coord_to_ft(y) < 150 for y in dlist])
  if node_count > 0:
    print(f"The following {node_count} nodes already exist close to the location you entered:")
    for i in range(node_count):
      dlist_ix = dlist.index(dlist_sorted[i])
      print(f"{i+1}: {map.nodeList[dlist_ix].lat}, {map.nodeList[dlist_ix].lon} ({CvtdUtil.coord_to_ft(dlist_sorted[i])} feet)")
    usenode = input("Use instead any of these nodes? Enter 'n' or number: ")
    try:
      usenode = int(usenode)
      if 1 <= usenode <= node_count:
        plist = map.get_node_usage(dlist_ix)
        if len(plist) > 0:
          print("The following roads use this node: ")
          for point in plist:
            print(p.addr_repr(map.roadList))
          okay = input("Okay (y/n): ")
          if okay.lower() != 'y':
            return None
        else:
          lat = map.nodeList[dlist_ix].lat
          lon = map.nodeList[dlist_ix].lon
          node_ix = dlist_ix
    except ValueError:
      # node_ix, lat and lot already have their desired values
      pass
  return node_ix, lat, lon
コード例 #12
0
    def compute_addr_repr(self, lat, lon, valid_streets):
        ix, address, error = self.compute_addr(lat, lon, valid_streets)
        if ix != -1:
            addrRepr = CvtdUtil.addr_repr(address, self.roadList[ix].dir,
                                          self.roadList[ix].name)
        else:
            addrRepr = "N/A"

        return ix, addrRepr, error
コード例 #13
0
ファイル: testCvtdUtil.py プロジェクト: kenyonsmith/cvtdapp
 def test_parse_csv(self):
     with open('tmpTest1.csv', 'w') as f:
         f.write('a,b,c\n')
         f.write('5,,6\n')
         f.write('1,2,\n')
         f.write(',,\n')
         f.write('x,y,z\n')
         f.write('"3,3","4,4","5,5"\n')
     result = CvtdUtil.parse_csv('tmpTest1.csv')
     os.remove('tmpTest1.csv')
     self.assertListEqual(['5', '1', '', 'x', '"3,3"'], result['a'])
     self.assertListEqual(['', '2', '', 'y', '"4,4"'], result['b'])
     self.assertListEqual(['6', '', '', 'z', '"5,5"'], result['c'])
コード例 #14
0
    def compute_addr(self, lat, lon, valid_streets):
        ix, seg_ix, proj_ratio, error = self.compute_proj_ratio(
            lat, lon, valid_streets)

        if ix != -1:
            vaddr_begin = self.roadList[ix].points[seg_ix].addr
            vaddr_end = self.roadList[ix].points[seg_ix + 1].addr

            address = round(proj_ratio * (vaddr_end - vaddr_begin) +
                            vaddr_begin)
        else:
            address = 0

        return ix, address, CvtdUtil.coord_to_ft(error)
コード例 #15
0
ファイル: gtfsShape.py プロジェクト: kenyonsmith/cvtdapp
  def get_min_point_error(self, lat, lon):
    min_pos_to_proj = 0x7FFFFFFF
    
    for point_ix, point in enumerate(self.pointList[:-1]):
      blon = point.lon
      blat = point.lat
      elon = self.pointList[point_ix + 1].lon
      elat = self.pointList[point_ix + 1].lat
      street_sc, pos_sc, projection_sc, begin_or_end = CvtdUtil.sub_proj_ratio(lat, lon, blat, blon, elat, elon)

      if projection_sc != 0.0:
        proj_sc_fixed = min(projection_sc, street_sc)
        try:
          pos_to_proj = math.sqrt((pos_sc * pos_sc) - (proj_sc_fixed * proj_sc_fixed))
        except ValueError:
          pos_to_proj = 0

        if pos_to_proj < min_pos_to_proj:
          min_pos_to_proj = pos_to_proj
      else:
        print(f"Error [get_min_point_error] on shape: two adjacent points with same node")
      
    return CvtdUtil.coord_to_ft(min_pos_to_proj)
コード例 #16
0
ファイル: gtfsImporter.py プロジェクト: kenyonsmith/cvtdapp
    def import_trips(dirPath, myMap):
        print("Importing trips...")
        tripDict = {}
        trips = CvtdUtil.parse_csv(dirPath + "/trips.txt")
        try:
            for ix, tid in enumerate(trips['trip_id']):
                if tid not in tripDict:
                    tripDict[tid] = GtfsTrip()
                tripDict[tid].routeId = trips['route_id'][ix]
                tripDict[tid].serviceId = trips['service_id'][ix]
                tripDict[tid].directionId = int(trips['direction_id'][ix])
                tripDict[tid].blockId = trips['block_id'][ix].replace('"', '')
                tripDict[tid].shapeId = int(trips['shape_id'][ix])
        except (KeyError, IndexError, ValueError):
            print(f"Error: import_trips, ix {ix}, tid {tid}")
            pass

        myMap.tripDict = tripDict
コード例 #17
0
ファイル: gtfsImporter.py プロジェクト: kenyonsmith/cvtdapp
    def import_routes(dirPath, myMap):
        print("Importing routes...")
        routeDict = {}
        routes = CvtdUtil.parse_csv(dirPath + "/routes.txt")
        try:
            for ix, rid in enumerate(routes['route_id']):
                if rid not in routeDict:
                    routeDict[rid] = GtfsStop()

                routeDict[rid].agencyId = routes['agency_id'][ix]
                routeDict[rid].routeShortName = routes['route_short_name'][ix]
                routeDict[rid].routeLongName = routes['route_long_name'][ix]
                routeDict[rid].routeDesc = routes['route_desc'][ix]
                routeDict[rid].routeType = int(routes['route_type'][ix])
        except (KeyError, IndexError, ValueError):
            print(f"Error: import_routes, ix {ix}, rid {rid}")
            pass

        myMap.routeDict = routeDict
コード例 #18
0
ファイル: gtfsImporter.py プロジェクト: kenyonsmith/cvtdapp
    def import_stop_times(dirPath, myMap):
        print("Importing stop times...")
        stopTimeDict = {}
        stopTimes = CvtdUtil.parse_csv(dirPath + "/stop_times.txt")
        try:
            for ix, tid in enumerate(stopTimes['trip_id']):
                sid = stopTimes['stop_id'][ix]
                if (tid, sid) not in stopTimeDict:
                    stopTimeDict[(tid, sid)] = GtfsStopTime()
                stopTimeDict[(tid,
                              sid)].departure = datetime.datetime.strptime(
                                  stopTimes['departure_time'][ix],
                                  "%H:%M:%S").time()
                stopTimeDict[(tid, sid)].arrival = datetime.datetime.strptime(
                    stopTimes['arrival_time'][ix], "%H:%M:%S").time()
                stopTimeDict[(
                    tid, sid)].timepoint = stopTimes['timepoint'][ix] == '1'
        except (KeyError, IndexError, ValueError):
            print(f"Error: import_stop_times, ix {ix}, tid {tid}, sid {sid}")
            pass

        myMap.stopTimeDict = stopTimeDict
コード例 #19
0
  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)
コード例 #20
0
ファイル: testCvtdUtil.py プロジェクト: kenyonsmith/cvtdapp
 def test_split_quotes_empty_field(self):
     s = "2,3,'boo',,\"hello\",,7"
     self.assertListEqual(["2", "3", "'boo'", "", "\"hello\"", "", "7"],
                          CvtdUtil.split_quotes(s, ','))
コード例 #21
0
 def addr_repr(self, roadList):
     return CvtdUtil.addr_repr(self.addr, roadList[self.roadIx].dir,
                               roadList[self.roadIx].name)
コード例 #22
0
 def addr_dir(self, roadList):
     return CvtdUtil.addr_dir(self.addr, roadList[self.roadIx].dir)
コード例 #23
0
  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
コード例 #24
0
ファイル: testCvtdUtil.py プロジェクト: kenyonsmith/cvtdapp
 def test_coord_to_ft(self):
     self.assertEqual(CvtdUtil.coord_to_ft(1), 369600)