def distance_from_location_using_u_v_w(cls, u=None, v=None, w=None, timestep=None, location=None): """ Calculate the greate distance from a location using u, v, and w. u, v, and w must be in the same units as the timestep. Stick with seconds. """ # Move horizontally distance_horiz = 0 azimuth = 0 angle = 0 depth = location.depth if u is not 0 and v is not 0: s_and_d = AsaMath.speed_direction_from_u_v(u=u,v=v) # calculates velocity in m/s from transformed u and v distance_horiz = s_and_d['speed'] * timestep # calculate the horizontal distance in meters using the velocity and model timestep angle = s_and_d['direction'] # Great circle calculation # Calculation takes in azimuth (heading from North, so convert our mathematical angle to azimuth) azimuth = AsaMath.math_angle_to_azimuth(angle=angle) distance_vert = 0. if w is not None: # Move vertically # Depth is positive up, negative down. w wil be negative if moving down, and positive if moving up distance_vert = w * timestep depth += distance_vert # calculate the vertical distance in meters using w (m/s) and model timestep (s) if distance_horiz != 0: vertical_angle = math.degrees(math.atan(distance_vert / distance_horiz)) gc_result = AsaGreatCircle.great_circle(distance=distance_horiz, azimuth=azimuth, start_point=location) else: # Did we go up or down? vertical_angle = 0. if distance_vert < 0: # Down vertical_angle = 270. elif distance_vert > 0: # Up vertical_angle = 90. gc_result = { 'latitude': location.latitude, 'longitude': location.longitude, 'reverse_azimuth': 0 } #logger.info("Particle moving from %fm to %fm from a vertical speed of %f m/s over %s seconds" % (location.depth, depth, w, str(timestep))) gc_result['azimuth'] = azimuth gc_result['depth'] = depth gc_result['distance'] = distance_horiz gc_result['angle'] = angle gc_result['vertical_distance'] = distance_vert gc_result['vertical_angle'] = vertical_angle return gc_result
def __bounce(self, **kwargs): """ Bounce off of the shoreline. NOTE: This does not work, but left here for future implementation feature = Linestring of two points, being the line segment the particle hit. angle = decimal degrees from 0 (x-axis), couter-clockwise (math style) """ start_point = kwargs.pop('start_point') hit_point = kwargs.pop('hit_point') end_point = kwargs.pop('end_point') feature = kwargs.pop('feature') distance = kwargs.pop('distance') angle = kwargs.pop('angle') # Figure out the angle of the shoreline here (beta) points_in_shore = map(lambda x: Point(x), list(feature.coords)) points_in_shore = sorted(points_in_shore, key=lambda x: x.x) # The point on the left (least longitude is always the first Point) first_shore = points_in_shore[0] last_shore = points_in_shore[-1] shoreline_x = abs(abs(first_shore.x) - abs(last_shore.x)) shoreline_y = abs(abs(first_shore.y) - abs(last_shore.y)) beta = math.degrees(math.atan(shoreline_x / shoreline_y)) theta = 90 - angle - beta bounce_azimuth = AsaMath.math_angle_to_azimuth(angle=2 * theta + angle) print "Beta: " + str(beta) print "Incoming Angle: " + str(angle) print "ShorelineAngle: " + str(theta + angle) print "Bounce Azimuth: " + str(bounce_azimuth) print "Bounce Angle: " + str( AsaMath.azimuth_to_math_angle(azimuth=bounce_azimuth)) after_distance = distance - AsaGreatCircle.great_distance( start_point=start_point, end_point=hit_point)['distance'] new_point = AsaGreatCircle.great_circle(distance=after_distance, azimuth=bounce_azimuth, start_point=hit_point) return Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth)
def __bounce(self, **kwargs): """ Bounce off of the shoreline. NOTE: This does not work, but left here for future implementation feature = Linestring of two points, being the line segment the particle hit. angle = decimal degrees from 0 (x-axis), couter-clockwise (math style) """ start_point = kwargs.pop("start_point") hit_point = kwargs.pop("hit_point") end_point = kwargs.pop("end_point") feature = kwargs.pop("feature") distance = kwargs.pop("distance") angle = kwargs.pop("angle") # Figure out the angle of the shoreline here (beta) points_in_shore = map(lambda x: Point(x), list(feature.coords)) points_in_shore = sorted(points_in_shore, key=lambda x: x.x) # The point on the left (least longitude is always the first Point) first_shore = points_in_shore[0] last_shore = points_in_shore[-1] shoreline_x = abs(abs(first_shore.x) - abs(last_shore.x)) shoreline_y = abs(abs(first_shore.y) - abs(last_shore.y)) beta = math.degrees(math.atan(shoreline_x / shoreline_y)) theta = 90 - angle - beta bounce_azimuth = AsaMath.math_angle_to_azimuth(angle=2 * theta + angle) print "Beta: " + str(beta) print "Incoming Angle: " + str(angle) print "ShorelineAngle: " + str(theta + angle) print "Bounce Azimuth: " + str(bounce_azimuth) print "Bounce Angle: " + str(AsaMath.azimuth_to_math_angle(azimuth=bounce_azimuth)) after_distance = ( distance - AsaGreatCircle.great_distance(start_point=start_point, end_point=hit_point)["distance"] ) new_point = AsaGreatCircle.great_circle(distance=after_distance, azimuth=bounce_azimuth, start_point=hit_point) return Location4D(latitude=new_point["latitude"], longitude=new_point["longitude"], depth=start_point.depth)
def test_math_angle_to_geo(self): azimuth = AsaMath.math_angle_to_azimuth(angle=90) assert azimuth == 0 azimuth = AsaMath.math_angle_to_azimuth(angle=180) assert azimuth == 270 azimuth = AsaMath.math_angle_to_azimuth(angle=0) assert azimuth == 90 azimuth = AsaMath.math_angle_to_azimuth(angle=360) assert azimuth == 90 azimuth = AsaMath.math_angle_to_azimuth(angle=270) assert azimuth == 180 azimuth = AsaMath.math_angle_to_azimuth(angle=45) assert azimuth == 45 azimuth = AsaMath.math_angle_to_azimuth(angle=232) assert azimuth == 218 azimuth = AsaMath.math_angle_to_azimuth(angle=45) assert azimuth == 45