def fish_distance(point1,point2): """ Returns the shortest distance around land (see the Land model) between the two points. Returns the distance in miles and the geos linestring that represents the path. NOTE: I'm assuming that the native units of the points and line is meters. This is true for the MLPA project but may not be true for other processes. """ # This is the straight line between the two points line = geos.LineString(point1,point2) # See if the straight line crosses land if line_crosses_land(line): # The straight line cut across land so we have to do it the hard way. G = PickledGraph.objects.all()[0].graph G = add_points_to_graph([point1,point2],G) # G.add_nodes_from([point1,point2]) # G = add_ocean_edges_for_node(G,get_node_from_point(G,point1)) # G = add_ocean_edges_for_node(G,get_node_from_point(G,point2)) # Replace the straight line with the shortest path around land line = geos.LineString( nx.dijkstra_path(G,get_node_from_point(G,point1),get_node_from_point(G,point2)) ) line.srid = settings.GEOMETRY_DB_SRID # Figure out the distance of the line (straight or otherwise) in miles distance = length_in_display_units(line) return distance, line
def distance_row_list(from_pnt, to_list): """ NOTE: This method assumes that the projection units are meters. """ result = [] for point in to_list: result.append(length_in_display_units(point.distance(from_pnt))) return result
def distance_row_dict(from_dict, to_dict): """ from_dict will be a dict with a point as the key and a label as the value. to_dict will be of the same format with multiple entries. will return a dictionary with points as keys and a dictionary as values. NOTE: This method assumes that the projection units are meters. """ from_pnt = from_dict.keys()[0] for s_pnt in SpacingPoint.objects.all(): to_dict.update({s_pnt.geometry:s_pnt.name}) result = {} for point, pnt_label in to_dict.iteritems(): result[point] = { 'label': pnt_label, 'distance': length_in_display_units(point.distance(from_pnt)), 'sort': point.y } return result
def distance_row_dict(from_dict, to_dict): """ from_dict will be a dict with a point as the key and a label as the value. to_dict will be of the same format with multiple entries. will return a dictionary with points as keys and a dictionary as values. NOTE: This method assumes that the projection units are meters. """ from_pnt = from_dict.keys()[0] for s_pnt in SpacingPoint.objects.all(): to_dict.update({s_pnt.geometry:s_pnt.name}) result = {} for point, pnt_label in to_dict.iteritems(): result[point] = { 'label': pnt_label, 'distance': length_in_display_units(point.distance(from_pnt)), 'sort': point.y } return result
def add_ocean_edges_complete(graph, verbose=False): if verbose: cnt = 1 import time t0 = time.time() print "Starting at %s to add edges for %i nodes." % (time.asctime(time.localtime(t0)), graph.number_of_nodes() ) edge_possibilities = graph.number_of_nodes() * (graph.number_of_nodes() -1) print "We'll have to look at somewhere around %i edge possibilities." % ( edge_possibilities ) print "Node: ", for node in graph.nodes_iter(): if verbose: print str(cnt) + ' ', cnt += 1 for n in graph.nodes_iter(): if node <> n: line = geos.LineString(node,n) if not line_crosses_land(line): graph.add_edge(node,n,{'weight': length_in_display_units(node.distance(n))}) if verbose: print "It took %i minutes to load %i edges." % ((time.time() - t0)/60, graph.number_of_edges() ) return graph
def fish_distance_from_edges(geom1,geom2): """ """ # Straight line between geoms line = shortest_line(geom1,geom2) # See if the line crosses land if line_crosses_land(line): # Get shortest centroid to centroid fish_distance line c_distance, c_line = fish_distance(geom1.centroid,geom2.centroid) # Replace the first point in the fish path with the point on geom1 # that lies closest to the second point on the path. #print c_line[1] c_line[0] = closest_point(geom1, geos.Point( c_line.coords[1], srid=geom1.srid ) ).coords # Do the same for the last point in the path c_line[c_line.num_points - 1] = closest_point(geom2, geos.Point( c_line.coords[c_line.num_points - 2], srid=geom2.srid ) ).coords line = c_line # Adjust the distance distance = length_in_display_units(line) return distance, line
def distance_row_list(from_pnt, to_list, straight_line=False, with_geom=False): """ NOTE: This method assumes that the projection units are meters. This should be changed. Check out lingcod.unit_converter.models. It's pretty easy to introspect the geometry for the srid and figure out the native units from that. I'd fix it but this is my last week here before taking a big trip on a small boat. """ result = [] for point in to_list: point_pair_dict = {} if straight_line: point_pair_dict.update( {'distance': length_in_display_units(point.distance(from_pnt)) } ) if with_geom: line = geos.LineString(point,from_pnt) else: distance, line = fish_distance_from_edges(from_pnt,point) point_pair_dict.update( {'distance': distance} ) if with_geom: point_pair_dict.update( {'geometry': line} ) result.append(point_pair_dict) return result
def add_ocean_edges_for_node(graph, node): for n in graph: line = geos.LineString(node,n) if not line_crosses_land(line): graph.add_edge(node,n,{'weight': length_in_display_units(node.distance(n))}) return graph