def generate_altitude_extremes(nodes, max_height=10000.0, min_height=-10000.0, max_distance=32000.0): # your everests, mariana trenches current_lowest_point = min(nodes, key=lambda n: n.altitude) points_to_adjust = [current_lowest_point] while len(points_to_adjust) > 0: point_to_adjust = points_to_adjust.pop() distance_from_origin = (geographic_utils.great_circle_distance(current_lowest_point.location, point_to_adjust.location) * 1000.0) if distance_from_origin > max_distance: continue inverted_height = -1.0 * min_height adjusted_altitude = -1.0 * (((inverted_height/100.0) * (1.0/(((max_distance/(-1.0*min_height))*distance_from_origin+(inverted_height/10.0))/(inverted_height*10.0)))) - (inverted_height/10.0)) if point_to_adjust.altitude < adjusted_altitude: points_to_adjust.extend(point_to_adjust.neighbours) point_to_adjust.altitude = adjusted_altitude current_highest_point = max(nodes, key=lambda n: n.altitude) points_to_adjust = [current_highest_point] while len(points_to_adjust) > 0: point_to_adjust = points_to_adjust.pop() distance_from_origin = (geographic_utils.great_circle_distance(current_highest_point.location, point_to_adjust.location) * 1000.0) if distance_from_origin > max_distance: continue adjusted_altitude = ((max_height/100.0) * (1.0/(((max_distance/max_height)*distance_from_origin+(max_height/10.0))/(max_height*10.0)))) - (max_height/10.0) if point_to_adjust.altitude < adjusted_altitude: points_to_adjust.extend(point_to_adjust.neighbours) point_to_adjust.altitude = adjusted_altitude
def generate_altitude_spikes(nodes, num_altitude_spikes, random_seed=117, altitude_feature=["terrain", "altitude"]): """ Random high points of altitude which grow outwards to affect nearby nodes """ for i in range(num_altitude_spikes): spike_height = 0.0 + random.uniform(0,0.8) # continent_radius = random.uniform(math.pi/8.0, math.pi/4.0) # print("Using spike_height {} and continient radius {}".format(spike_height, continent_radius)) epicentre = random.choice(nodes) # falloff_angle_distance = random.randint(10, 60) falloff_great_circle_vertical = random.uniform(0.125 * math.pi/3.0, math.pi/3.0) # make sure no continent gets bigger than a third of the height or a third of the width falloff_great_circle_horizontal = random.uniform(0.1 * 2.0 * math.pi/3.0, 2.0 * math.pi/3.0) # make sure no continent gets bigger than a third of the height or a third of the width # search outwards from epicentre settings altitude leaves = [epicentre] for leaf in leaves: # Set altitude here # great_circle_distance = spherepoints.great_circle_distance((epicentre.lon, epicentre.lat), (leaf.lon, leaf.lat)) # print("Leaf is {} units from epicentre {}".format(great_circle_distance, epicentre)) # if great_circle_distance > continent_radius: # continue # else: # leaf.set_feature(altitude_feature, (1.0 - (great_circle_distance / continent_radius)) * spike_height) vertical_distance = geographic_utils.great_circle_distance((0.0, epicentre.lat), (0.0, leaf.lat)) horizontal_distance = geographic_utils.great_circle_distance((epicentre.lon, 0.0), (leaf.lon, 0.0)) # avg_angle_diff = (abs(epicentre.lon - leaf.lon) + abs(epicentre.lat - leaf.lat))/2 # if avg_angle_diff > falloff_angle_distance: # # Out of range. No alteration to altitude. # continue if vertical_distance > falloff_great_circle_vertical or horizontal_distance > falloff_great_circle_horizontal: continue # falloff_factor = (vertical_distance/falloff_great_circle_vertical + horizontal_distance/falloff_great_circle_horizontal) / 2.0 # leaf.set_feature(altitude_feature, spike_height * (1 - falloff_factor) + random.uniform(0.01, 0.05)) leaf.set_feature(altitude_feature, (spike_height - (geographic_utils.great_circle_distance((epicentre.lon, epicentre.lat), (leaf.lon, leaf.lat))*spike_height)) * random.uniform(0.9, 1.1)) # print("Setting leaf altitude to {}".format(leaf.features["terrain"]["altitude"])) # Continue on to neighbours for neighbour in leaf.neighbours: if random.random() < 0.2: # Early termination of this search path # Set altitude to beach level as this will be coastal neighbour.get_feature(altitude_feature[:-1])["altitude"] *= 0.5 # continue if neighbour not in leaves: leaves.append(neighbour)
def find_nearest_cell(candidate_cells, p_lon, p_lat): """ Currently an exhaustive search of all cells :param candidate_cells: list of Cell objects to be searched :param p_lon: longitude :param p_lat: latitude :return: """ shortest_dist = None nearest_cell = None for c in candidate_cells: dist = geographic_utils.great_circle_distance(c.centre.loc, (p_lon, p_lat)) if nearest_cell is None or dist < shortest_dist: nearest_cell = c shortest_dist = dist return nearest_cell
def find_nearest_node_using_cells(candidate_cells, p_lon, p_lat): """ Finds the cell boundary SpatialNode, belonging to Cell within candidate cells, that is nearest to provided lon, lat location :param candidate_cells: list of Cell objects to be searched :param p_lon: longitude of point :param p_lat: latitude of point :return: SpatialNode (in a cell boundary) which is nearest to p_lon, p_lat """ nearest_cell = find_nearest_cell(candidate_cells, p_lon, p_lat) shortest_dist = None nearest_node = None for n in nearest_cell.nodes: dist = geographic_utils.great_circle_distance(n.loc, (p_lon, p_lat)) if nearest_node == None or dist < shortest_dist: nearest_node = n shortest_dist = dist return nearest_node
def generate_rainfall(nodes, max_distance=5000.0): from everett.spherepoints import geographic_utils for node in nodes: if node.get_feature(['surface', 'type']) == 0: # evaporate some seawater evaporation = node.sea_temperature cloud_life = evaporation * 50.0 cloud_height = 1000.0 cloud_distance = 0.0 current_node = node while cloud_life > 0 and cloud_distance < max_distance: dwn = node.downwind_neighbour if dwn is None: cloud_life = 0.0 break cloud_distance += geographic_utils.great_circle_distance(dwn.location, current_node.location)*1000.0 # dwn_rf = dwn.get_feature(['precipitation', 'mm']) # if dwn_rf is None: # dwn_rf = 0.0 # dwn.set_feature(['precipitation', 'mm'], dwn_rf + cloud_life) cloud_life -= 1.0 current_node = dwn current_rainfall = current_node.get_feature(['precipitation', 'mm'], default=0.0) current_node.set_feature(['precipitation', 'mm'], current_rainfall + evaporation)