def compute_distance_to_nodes(self, x, y, edge): """ Given an observation on a network edge, return the distance to the two nodes that bound that end. Parameters ---------- x: float x-coordinate of the snapped point. y: float y-coordiante of the snapped point. edge: tuple (node0, node1) representation of the network edge. Returns ------- d1: float The distance to node0. - always the node with the lesser id d2: float The distance to node1. - always the node with the greater id """ d1 = util.compute_length((x, y), self.node_coords[edge[0]]) d2 = util.compute_length((x, y), self.node_coords[edge[1]]) return d1, d2
def compute_distance_to_nodes(self, x, y, edge): """ Given an observation on a network edge, return the distance to the two nodes that bound that end. Parameters ---------- x: float x-coordinate of the snapped point. y: float y-coordiante of the snapped point. edge: tuple (node0, node1) representation of the network edge. Returns ------- d1: float The distance to node0. - always the node with the lesser id d2: float The distance to node1. - always the node with the greater id """ d1 = util.compute_length((x,y), self.node_coords[edge[0]]) d2 = util.compute_length((x,y), self.node_coords[edge[1]]) return d1, d2
def extractnetwork(self): """ Using the same logic as the high efficiency areal unit weights creation extract the network from the edges / vertices. """ nodecount = 0 edgetpl = namedtuple('Edge', ['source', 'destination']) shps = ps.open(self.in_shp) for shp in shps: vertices = shp.vertices for i, v in enumerate(vertices[:-1]): try: vid = self.nodes[v] except: self.nodes[v] = vid = nodecount nodecount += 1 try: nvid = self.nodes[vertices[i+1]] except: self.nodes[vertices[i+1]] = nvid = nodecount nodecount += 1 self.adjacencylist[vid].append(nvid) self.adjacencylist[nvid].append(vid) #Sort the edges so that mono-directional keys can be stored. edgenodes = sorted([vid, nvid]) edge = tuple(edgenodes) self.edges.append(edge) length = util.compute_length(v, vertices[i+1]) self.edge_lengths[edge] = length
def _extractnetwork(self): """ Used internally, to extract a network from a polyline shapefile """ nodecount = 0 shps = ps.open(self.in_shp) for shp in shps: vertices = shp.vertices for i, v in enumerate(vertices[:-1]): try: vid = self.nodes[v] except: self.nodes[v] = vid = nodecount nodecount += 1 try: nvid = self.nodes[vertices[i + 1]] except: self.nodes[vertices[i + 1]] = nvid = nodecount nodecount += 1 self.adjacencylist[vid].append(nvid) self.adjacencylist[nvid].append(vid) #Sort the edges so that mono-directional keys can be stored. edgenodes = sorted([vid, nvid]) edge = tuple(edgenodes) self.edges.append(edge) length = util.compute_length(v, vertices[i + 1]) self.edge_lengths[edge] = length
def _extractnetwork(self): """ Used internally, to extract a network from a polyline shapefile """ nodecount = 0 shps = ps.open(self.in_shp) for shp in shps: vertices = shp.vertices for i, v in enumerate(vertices[:-1]): try: vid = self.nodes[v] except: self.nodes[v] = vid = nodecount nodecount += 1 try: nvid = self.nodes[vertices[i+1]] except: self.nodes[vertices[i+1]] = nvid = nodecount nodecount += 1 self.adjacencylist[vid].append(nvid) self.adjacencylist[nvid].append(vid) #Sort the edges so that mono-directional keys can be stored. edgenodes = sorted([vid, nvid]) edge = tuple(edgenodes) self.edges.append(edge) length = util.compute_length(v, vertices[i+1]) self.edge_lengths[edge] = length
def _extractnetwork(self): """ Used internally, to extract a network from a polyline shapefile. """ nodecount = 0 shps = ps.open(self.in_shp) for shp in shps: vertices = shp.vertices for i, v in enumerate(vertices[:-1]): v = self._round_sig(v) try: vid = self.nodes[v] except: self.nodes[v] = vid = nodecount nodecount += 1 v2 = self._round_sig(vertices[i + 1]) try: nvid = self.nodes[v2] except: self.nodes[v2] = nvid = nodecount nodecount += 1 self.adjacencylist[vid].append(nvid) self.adjacencylist[nvid].append(vid) # Sort the edges so that mono-directional keys can be stored. edgenodes = sorted([vid, nvid]) edge = tuple(edgenodes) self.edges.append(edge) length = util.compute_length(v, vertices[i + 1]) self.edge_lengths[edge] = length if self.unique_segs == True: # Remove duplicate edges and duplicate adjacent nodes. self.edges = list(set(self.edges)) for k, v in self.adjacencylist.iteritems(): self.adjacencylist[k] = list(set(v))
def _extractnetwork(self): """ Used internally, to extract a network from a polyline shapefile. """ nodecount = 0 shps = ps.open(self.in_shp) for shp in shps: vertices = shp.vertices for i, v in enumerate(vertices[:-1]): v = self._round_sig(v) try: vid = self.nodes[v] except: self.nodes[v] = vid = nodecount nodecount += 1 v2 = self._round_sig(vertices[i+1]) try: nvid = self.nodes[v2] except: self.nodes[v2] = nvid = nodecount nodecount += 1 self.adjacencylist[vid].append(nvid) self.adjacencylist[nvid].append(vid) # Sort the edges so that mono-directional keys can be stored. edgenodes = sorted([vid, nvid]) edge = tuple(edgenodes) self.edges.append(edge) length = util.compute_length(v, vertices[i+1]) self.edge_lengths[edge] = length if self.unique_segs == True: # Remove duplicate edges and duplicate adjacent nodes. self.edges = list(set(self.edges)) for k, v in self.adjacencylist.iteritems(): self.adjacencylist[k] = list(set(v))
def allneighbordistances(self, sourcepattern, destpattern=None, fill_diagonal=None, n_processes=None): """ Compute either all distances between i and j in a single point pattern or all distances between each i from a source pattern and all j from a destination pattern. Parameters ---------- sourcepattern: str The key of a point pattern snapped to the network. destpattern: str (Optional) The key of a point pattern snapped to the network. fill_diagonal: float, int (Optional) Fill the diagonal of the cost matrix. Default in None and will populate the diagonal with numpy.nan Do not declare a destpattern for a custom fill_diagonal. n_processes: int, str (Optional) Specify the number of cores to utilize. Default is 1 core. Use (int) to specify an exact number or cores. Use ("all") to request all available cores. Returns ------- nearest: array (n,n) An array of shape (n,n) storing distances between all points. """ if not hasattr(self, 'alldistances'): self.node_distance_matrix(n_processes) # Source setup src_indices = sourcepattern.points.keys() nsource_pts = len(src_indices) src_dist_to_node = sourcepattern.dist_to_node src_nodes = {} for s in src_indices: e1, e2 = src_dist_to_node[s].keys() src_nodes[s] = (e1, e2) # Destination setup symmetric = False if destpattern is None: symmetric = True destpattern = sourcepattern dest_indices = destpattern.points.keys() ndest_pts = len(dest_indices) dest_dist_to_node = destpattern.dist_to_node dest_searchpts = copy.deepcopy(dest_indices) dest_nodes = {} for s in dest_indices: e1, e2 = dest_dist_to_node[s].keys() dest_nodes[s] = (e1, e2) # Output setup nearest = np.empty((nsource_pts, ndest_pts)) nearest[:] = np.inf for p1 in src_indices: # Get the source nodes and dist to source nodes. source1, source2 = src_nodes[p1] set1 = set(src_nodes[p1]) # Distance from node1 to p, distance from node2 to p. sdist1, sdist2 = src_dist_to_node[p1].values() if symmetric: # Only compute the upper triangle if symmetric. dest_searchpts.remove(p1) for p2 in dest_searchpts: dest1, dest2 = dest_nodes[p2] set2 = set(dest_nodes[p2]) if set1 == set2: # same edge x1, y1 = sourcepattern.snapped_coordinates[p1] x2, y2 = destpattern.snapped_coordinates[p2] computed_length = util.compute_length((x1, y1), (x2, y2)) nearest[p1, p2] = computed_length else: ddist1, ddist2 = dest_dist_to_node[p2].values() d11 = self.alldistances[source1][0][dest1] d21 = self.alldistances[source2][0][dest1] d12 = self.alldistances[source1][0][dest2] d22 = self.alldistances[source2][0][dest2] # Find the shortest distance from the path passing through each of the # two origin nodes to the first destination node. sd_1 = d11 + sdist1 sd_21 = d21 + sdist2 if sd_1 > sd_21: sd_1 = sd_21 # Now add the point to node one distance on the destination edge. len_1 = sd_1 + ddist1 # Repeat the prior but now for the paths entering at the second node # of the second edge. sd_2 = d12 + sdist1 sd_22 = d22 + sdist2 b = 0 if sd_2 > sd_22: sd_2 = sd_22 b = 1 len_2 = sd_2 + ddist2 # Now find the shortest distance path between point 1 on edge 1 and # point 2 on edge 2, and assign. sp_12 = len_1 if len_1 > len_2: sp_12 = len_2 nearest[p1, p2] = sp_12 if symmetric: # Mirror the upper and lower triangle when symmetric. nearest[p2, p1] = nearest[p1, p2] # Populate the main diagonal when symmetric. if symmetric: if fill_diagonal == None: np.fill_diagonal(nearest, np.nan) else: np.fill_diagonal(nearest, fill_diagonal) return nearest
def allneighbordistances(self, sourcepattern, destpattern=None, fill_diagonal=None, n_processes=None): """ Compute either all distances between i and j in a single point pattern or all distances between each i from a source pattern and all j from a destination pattern. Parameters ---------- sourcepattern: str The key of a point pattern snapped to the network. destpattern: str (Optional) The key of a point pattern snapped to the network. fill_diagonal: float, int (Optional) Fill the diagonal of the cost matrix. Default in None and will populate the diagonal with numpy.nan Do not declare a destpattern for a custom fill_diagonal. n_processes: int, str (Optional) Specify the number of cores to utilize. Default is 1 core. Use (int) to specify an exact number or cores. Use ("all") to request all available cores. Returns ------- nearest: array (n,n) An array of shape (n,n) storing distances between all points. """ if not hasattr(self,'alldistances'): self.node_distance_matrix(n_processes) # Source setup src_indices = sourcepattern.points.keys() nsource_pts = len(src_indices) src_dist_to_node = sourcepattern.dist_to_node src_nodes = {} for s in src_indices: e1, e2 = src_dist_to_node[s].keys() src_nodes[s] = (e1, e2) # Destination setup symmetric = False if destpattern is None: symmetric = True destpattern = sourcepattern dest_indices = destpattern.points.keys() ndest_pts = len(dest_indices) dest_dist_to_node = destpattern.dist_to_node dest_searchpts = copy.deepcopy(dest_indices) dest_nodes = {} for s in dest_indices: e1, e2 = dest_dist_to_node[s].keys() dest_nodes[s] = (e1, e2) # Output setup nearest = np.empty((nsource_pts, ndest_pts)) nearest[:] = np.inf for p1 in src_indices: # Get the source nodes and dist to source nodes. source1, source2 = src_nodes[p1] set1 = set(src_nodes[p1]) # Distance from node1 to p, distance from node2 to p. sdist1, sdist2 = src_dist_to_node[p1].values() if symmetric: # Only compute the upper triangle if symmetric. dest_searchpts.remove(p1) for p2 in dest_searchpts: dest1, dest2 = dest_nodes[p2] set2 = set(dest_nodes[p2]) if set1 == set2: # same edge x1,y1 = sourcepattern.snapped_coordinates[p1] x2,y2 = destpattern.snapped_coordinates[p2] computed_length = util.compute_length((x1,y1),(x2,y2)) nearest[p1,p2] = computed_length else: ddist1, ddist2 = dest_dist_to_node[p2].values() d11 = self.alldistances[source1][0][dest1] d21 = self.alldistances[source2][0][dest1] d12 = self.alldistances[source1][0][dest2] d22 = self.alldistances[source2][0][dest2] # Find the shortest distance from the path passing through each of the # two origin nodes to the first destination node. sd_1 = d11 + sdist1 sd_21 = d21 + sdist2 if sd_1 > sd_21: sd_1 = sd_21 # Now add the point to node one distance on the destination edge. len_1 = sd_1 + ddist1 # Repeat the prior but now for the paths entering at the second node # of the second edge. sd_2 = d12 + sdist1 sd_22 = d22 + sdist2 b = 0 if sd_2 > sd_22: sd_2 = sd_22 b = 1 len_2 = sd_2 + ddist2 # Now find the shortest distance path between point 1 on edge 1 and # point 2 on edge 2, and assign. sp_12 = len_1 if len_1 > len_2: sp_12 = len_2 nearest[p1, p2] = sp_12 if symmetric: # Mirror the upper and lower triangle when symmetric. nearest[p2,p1] = nearest[p1,p2] # Populate the main diagonal when symmetric. if symmetric: if fill_diagonal == None: np.fill_diagonal(nearest, np.nan) else: np.fill_diagonal(nearest, fill_diagonal) return nearest