def check_segment( segment, roadmap, length_attr='length' ) :
    # a rare case where "static variable" is useful;
    # to prevent "costly" re-allocation of RoadAddress structure
    if not hasattr(check_segment, 'first' ) :
        check_segment.first = RoadAddress(None,None)
    if not hasattr(check_segment, 'second' ) :
        check_segment.second = RoadAddress(None,None)
        
    road = segment.road
    check_segment.first.road = road
    check_segment.first.coord = segment.first
    check_segment.second.road = road
    check_segment.second.coord = segment.second
    
    try :
        assert check_point( roadmap, check_segment.first, length_attr )
        assert check_point( roadmap, check_segment.second, length_attr )
    except AssertionError :
        return False
    
    return True
def minpath_on_road( p, q, road, roadmap, length_attr='length' ) :
    """
    subroutine and useful utility:
    returns the path from p to q on road, if the direction of travel is admissible;
    if not, or if p and q are not co-'road'-al, returns empty path, implying non-existence 
    """ 
    edge, data  = obtain_edge( roadmap, road, True )
    i,j,key     = edge
    
    path = []
    # regular logic, NOT error catching
    try :
        assert p.road == road and check_point( roadmap, p, length_attr )
        assert q.road == road and check_point( roadmap, q, length_attr )
        assert p.coord < q.coord or not data.get( 'oneway', False )
        path.append( RoadSegment( road, p.coord, q.coord ) )
        
    except AssertionError :
        pass
    
    return path
def minpath_node_to_point( u, q, roadmap, length_attr='length' ) :
    """
    subroutine and useful utility:
    returns the shortest-path distance from a node u to a point q, on digraph    
    """
    
    # some convenient static variables
    scope = minpath_node_to_point
    if not hasattr( scope, 'STATICS' ) :
        scope.STATICS = True
        scope.first = RoadAddress(None,None)
        scope.second = RoadAddress(None,None)
        scope.points = [ scope.first, scope.second ]
    
    # convenient non-static variables
    assert check_point( roadmap, q, length_attr )
    road        = q.road
    edge, data  = obtain_edge( roadmap, road, True )
    i,j,key     = edge
    roadlen = data.get( length_attr, 1 )
    
    # pre-load options with nopath; in case there are no feasible paths
    options = [ (np.inf, [] ) ]
    
    # possible paths are u->v->q, for v in endpoints of road of q
    scope.first.init(road,0.)
    scope.second.init(road,roadlen)
    for v, pp in zip( (i,j), scope.points ) :
        try :
            astarPath = astar_basic.astar_path( roadmap, u, v, None, weight=length_attr )
            first = pathFromAStar( astarPath, roadmap, length_attr )
        except nx.NetworkXNoPath :
            continue
        second = minpath_on_road( pp, q, road, roadmap, length_attr )
        path = first + second
        options.append( (pathLength(path), path ) )
        
    return min( options )[1]