def resample_track_list(track, step, include_existing_points=True): if len(track) == 0: return [] distance = 0 target_distance = step old_location = eV.LatLon(track[0][1], track[0][0]) new_track = [_get_lonlat(old_location)] for _location in track[1:]: current_location = eV.LatLon(_location[1], _location[0]) segment_length, bearing = old_location.distanceTo3( current_location)[:2] segment_end = distance + segment_length for target_distance in np.arange(target_distance, segment_end, step): old_location = old_location.destination(target_distance - distance, bearing) new_track.append(_get_lonlat(old_location)) distance = target_distance existing_point = _get_lonlat(current_location) distance = segment_end if include_existing_points and existing_point != new_track[-1]: new_track.append(existing_point) target_distance = segment_end + step elif not include_existing_points: target_distance += step old_location = current_location last_item = _get_lonlat(old_location) if not include_existing_points and new_track[-1] != last_item: new_track.append(last_item) return new_track
def next_point(pointA, pointB, speed): start_point = ellipsoidalVincenty.LatLon(pointA.Lat, pointA.Long) end_point = ellipsoidalVincenty.LatLon(pointB.Lat, pointB.Long) new_point = start_point.destination(speed, start_point.initialBearingTo(end_point)) point = Point() point.new(lat=new_point.lat, long= new_point.lon) return point
def get_min_height(self, lat_ll, lon_ll, lat_ur, lon_ur): result = { 'location_min': [], 'h_min': self.NODATA, 'counter_min': 0, 'source': self.attribution_name, 'attributions': [self.attribution] } if not (-90 <= lat_ll <= 90 and -180 <= lon_ll <= 180 and -90 <= lat_ur <= 90 and -180 <= lon_ur <= 180): raise ValueError('invalid coordinates ({}, {}), ({}, {})'.format( lat_ll, lon_ll, lat_ur, lon_ur)) # consider only correctly defined rectangle: if lat_ll > lat_ur or lon_ll > lon_ur: return result try: osgr_ll = toOsgr(eV.LatLon(lat_ll, lon_ll)) if len(osgr_ll.toStr()) == 0: raise ValueError('not a valid OSGR coordinate') except ValueError: return result try: osgr_ur = toOsgr(eV.LatLon(lat_ur, lon_ur)) if len(osgr_ur.toStr()) == 0: raise ValueError('not a valid OSGR coordinate') except ValueError: return result file_list = {} try: self.create_filelist(osgr_ll, osgr_ur, file_list) except IOError: return result result.update(self.check_min_files(self.filter_min_list(file_list))) return result
def cal_route_dist_time_diff(route: list) -> list: """ calculate each route distance and time firstly, and then calculate the difference of distance and time between each route. :param route: list :return:[['distance', 'time'], [...], [...], ...] """ route_latlon_time = [] if (len(route) > 1): for i in range(1, len(route)): latlon = ev.LatLon(route[i - 1][4], route[i - 1][5]) latlon_next = ev.LatLon(route[i][4], route[i][5]) date = route[i - 1][0] + route[i - 1][1] date_next = route[i][0] + route[i][1] route_latlon_time = route_latlon_time + [[ meter_to_nm(latlon.distanceTo(latlon_next)), hour_diff_in_hr(date, date_next) ]] else: route_latlon_time = [[0.0, 1.0]] return route_latlon_time
def get_storm_maxspeed(eachstorm: dict) -> float: """ extract the maximum speed for each storm moving track :param eachstorm: a dictionary contains keys (coordinate, time, id and so on) :return: each storm max speed as a float """ max_speed = - math.inf storm_coordinate = eachstorm["coordinate"] # list storm_time = eachstorm["time"] # list if len(storm_coordinate) <= 1: return 0.0 for i in range(1, len(storm_coordinate)): a = ev.LatLon(storm_coordinate[i - 1][0], storm_coordinate[i - 1][1]) b = ev.LatLon(storm_coordinate[i][0], storm_coordinate[i][1]) if a == b: d = 0.0 else: d = a.distanceTo(b) ta = datetime.strptime(''.join(storm_time[i - 1]), "%Y%m%d%H%M") tb = datetime.strptime(''.join(storm_time[i]), "%Y%m%d%H%M") t = (tb - ta).total_seconds() / 3600 speed = (d / 1852) / t max_speed = max(speed, max_speed) return max_speed
def get_storm_avespeed(eachstorm: dict) -> float: """ calculate each storm average moving speed :param eachstorm: a dictionary contains keys (coordinate, time, id and so on) :return: each storm average speed as float """ total = 0 storm_coordinate = eachstorm["coordinate"] # list storm_time = eachstorm["time"] # list start = datetime.strptime(''.join(storm_time[0]), "%Y%m%d%H%M") stop = datetime.strptime(''.join(storm_time[-1]), "%Y%m%d%H%M") total_time = (stop - start).total_seconds() / 3600 if len(storm_coordinate) <= 1: return 0.0 for i in range(1, len(storm_coordinate)): a = ev.LatLon(storm_coordinate[i][0], storm_coordinate[i][1]) b = ev.LatLon(storm_coordinate[i - 1][0], storm_coordinate[i - 1][1]) if a == b: d = 0.0 else: d = a.distanceTo(b) total += d return (total / 1852) / total_time
def calulate_distance_and_speed(lat_list: list, lon_list: list, data_set_cur_time_list: list): ''' Calculates the maximum and mean speed the storm centre has moved. Also calculates the total distance the storm has moved. :param lat_list: Inputs a list of latitudes :param lon_list: Inputs a list of latitudes :param data_set_cur_time_list: Inputs a list of times :return: ''' dist_meters = 0 tot_dist_meters = 0 for i in range(len(lon_list) - 1): ini_pos = ev.LatLon(lat_list[i], lon_list[i]) fin_pos = ev.LatLon(lat_list[i + 1], lon_list[i + 1]) try: dist_meters = ini_pos.distanceTo( fin_pos) / 1852 #Convert to nautical miles except ev.VincentyError: dist_meters = 0 tot_dist_meters = tot_dist_meters + dist_meters time_diff = calc_time_diff(data_set_cur_time_list[i], data_set_cur_time_list[i + 1]) data_set_speed_list.append(dist_meters / time_diff) if not data_set_speed_list: data_set_speed_list.append(0.0) print("Max speed is: ", round(max(data_set_speed_list), 5), " Nautical Miles/Minute") print("Mean speed is: ", round(mean(data_set_speed_list), 5), " Nautical Miles/Minute") print("Total distance the storm was tracked", round((tot_dist_meters), 5), " Nautical Miles") return tot_dist_meters
def disCalculate(location1, location2): # function to calculate storm moving distance distance = [] # prepare all the lists for calculating variables Lation = [] total = 0 for a in range( len(location1) ): # calculation all the lat long to find the distance then add them together Lation.append(ev.LatLon(location1[a], location2[a])) for b in range((len(location1) - 1)): distance.append(Lation[b].distanceTo(Lation[b + 1]) / 1852.0) for c in range(len(distance)): total = total + distance[c] distance.clear() # clear variable list for next use Lation.clear() if total == 0: line_list.append("N/A") # this append to output table # print('The Storm did not move!') else: total = str(round(total, 2)) line_list.append(str(total)) # print('The distance it traveled is:', total) return total
def speed_cal(locations, time): """ calculate the speed of the storm :param locations: a list of nodes containing the longitude and the latitude of locations :param time: a list of time containing the time that a storm travels from one spot to another :return: a list of storm speed """ if len(locations) == 1: speed1 = 0 else: node = [] p = 0 while p < len(locations): node.append(ev.LatLon(locations[p][0], locations[p][1])) p += 1 j = 0 temp_dis = [] while j < (len(locations) - 1): temp_dis.append(node[j].distanceTo(node[j + 1])) j += 1 speed1 = [] for p in range(len(time)): if time == 0: speed1.append(0) else: speed1.append((int(temp_dis[p]) / 1852.0) / time[p]) return speed1
def get_hypo_quadrant(coordinate_1, coordinate_2: tuple) -> int: """ calculate hypothesized quadrant for a moving direction of a storm :param coordinate_1: for each storm, each track coordinate as a tuple :param coordinate_2: for each storm, each track coordinate as a tuple :return: int: quadrant index """ a = ev.LatLon(coordinate_1[0], coordinate_1[1]) b = ev.LatLon(coordinate_2[0], coordinate_2[1]) if a == b: bearing = 90 else: bearing = (int(a.bearingTo(b)) + 90) % 360 return bearing // 90
def myLatLon(lat: str, lon: str) -> ev.LatLon: """Given a latitude and longitude, normalize the longitude if necessary, to return a valid ellipsoidalVincenty.LatLon object. :param lat: the latitude as a string :param lon: the longitude as a string >>> a = ev.LatLon('45.1N', '2.0E') >>> my_a = myLatLon('45.1N', '2.0E') >>> a == my_a True >>> my_b = myLatLon('45.1N', '358.0W') >>> a == my_b # make sure it normalizes properly True >>> myLatLon('15.1', '68.0') LatLon(15°06′00.0″N, 068°00′00.0″E) """ if lon[-1] in ['E', 'W']: # parse string to separate direction from number portion: lon_num = float(lon[:-1]) lon_dir = lon[-1] else: lon_num = float(lon) if lon_num > 180.0: # Does longitude exceed range? lon_num = 360.0 - lon_num lon_dir = flip_direction(lon_dir) lon = str(lon_num) + lon_dir return ev.LatLon(lat, lon)
def get_degree(points): """ Calculating directional changes between samples :param points: A list of latitude and longitude pairs :return: degree: a list of diretional changes. """ loc = [] degree = [] for i in range(len(points)): loc.append(ev.LatLon(points[i][0], points[i][1])) for j in range(len(loc) - 1): if loc[j] != loc[j + 1]: d = loc[j].bearingTo(loc[j + 1]) if d <= 180: degree.append(d) else: degree.append( 360 - d ) # For example, a directional change of 200 degrees, clockwise, # in fact, would be the same with a directional change of 160 degrees, anticlockwise. else: degree.append( int(0) ) # bearingTo funcion would report error when two same latitude and longitude pairs are given return degree
def get_track_length(track: List[Location]): distance = 0 old_location = None for _location in track: current_location = eV.LatLon(_location.lat, _location.lon) if old_location: distance += old_location.distanceTo(current_location) old_location = current_location return round(distance, 3)
def connect_building_and_street(self): """ this function will connect building and each street connected to the building this will add the edge between two nodes in path_graph :return: None """ for x in range(self.edges.shape[0]): edge = self.edges.iloc[x] street = self.path_graph.node[edge.node_a + "-" + edge.node_b] building = "" if edge.node_a in self.path_graph.node: building = edge.node_a if edge.node_b in self.path_graph.node: building = edge.node_b if building != "": start = self.path_graph.node[building] if "coor" in start: coor = start["coor"].split(",") start_coor = ev.LatLon(coor[0], coor[1]) if "coor" in street: coor = street["coor"].split(",") end_coor = ev.LatLon(coor[0], coor[1]) dist, bearing, _ = start_coor.distanceTo3(end_coor) goto = self.convert_bearing_to_direction(bearing) # directed graph self.path_graph.add_edge(building, edge.node_a + "-" + edge.node_b, { "weight": dist, "bearing": bearing, "goto": goto }) bearing = bearing + 180 bearing = (bearing - 360) if bearing > 360 else bearing goto = self.convert_bearing_to_direction(bearing) self.path_graph.add_edge(edge.node_a + "-" + edge.node_b, building, { "weight": dist, "bearing": bearing, "goto": goto })
def wind_distance(): wind_d = [] wind_dper = [] for j in range(count): try: Lat_sum1, Lont_sum1 = Lat_sums[j], Lont_sums[j] x = [] x.append(ev.LatLon(Lat_sum1[0], Lont_sum1[0])) xs = [] for i in range(recordP_sum[j] - 1): x.append(ev.LatLon(Lat_sum1[i + 1], Lont_sum1[i + 1])) xs.append(x[i + 1].distanceTo(x[i]) / 1852) wind_d.append( sum(xs)) # sum the distances for one storm and append them wind_dper.append( xs) # append per distance between two points for every storm except Exception: wind_dper.append(0) wind_d.append(wind_d[-1]) return [wind_d, wind_dper]
def get_storm_distance(storm_coordinate: list) -> float: """ get each storm total moving distance :param storm_coordinate: list of tuples, each tuple contains a latitude and longitude :return: each storm total distance as a float """ total = 0 if len(storm_coordinate) <= 1: return 0.0 for i in range(1, len(storm_coordinate)): a = ev.LatLon(storm_coordinate[i][0], storm_coordinate[i][1]) b = ev.LatLon(storm_coordinate[i - 1][0], storm_coordinate[i - 1][1]) if a == b: d = 0.0 else: d = a.distanceTo(b) total += d return total / 1852 # Divide to convert meters into nautical miles
def SpeedCalculate(location1, location2, date, time): # function to calculate propagation speed epoch = [] distance = [] Lation = [] speed = [] total = 0 epc = 0 for a in range(len(location1)): Lation.append(ev.LatLon(location1[a], location2[a])) for b in range((len(location1) - 1)): distance.append(Lation[b].distanceTo(Lation[b + 1]) / 1852.0) if (int(date[b + 1]) - int(date[b])) > 0: ep = int(time[b + 1]) - int(time[b]) + 2400 else: ep = int(time[b + 1]) - int(time[b]) if ep % 100 == 0: epo = float(ep / 100) else: epo = ep // 100 + float((ep % 100) / 60) epoch.append(epo) for c in range(len(distance)): speed.append(distance[c] / epoch[c]) total = total + distance[c] epc = epc + epoch[c] if speed == []: mean_list.append(0) line_list.append('N/A') # append to table line_list.append('N/A') # print('The Storm did not have speed!') else: mean_speed = total / epc max_speed = max(speed) mean_list.append(mean_speed) epoch.clear() distance.clear() Lation.clear() speed.clear() # if max_speed == 0.0: # max_speed = str(max_speed)+"\t\t" # if mean_speed == 0.0: # mean_speed = str(mean_speed)+"\t\t" if mean_speed == 0.0: line_list.append(str(mean_speed)) if max_speed == 0.0: line_list.append(str(max_speed)) line_list.append(str(round( mean_speed, 2))) # append to table, rounded to 2 significant digit line_list.append(str(round(max_speed, 2))) # print('The mean propagation speed is: (Knots)', mean_speed, 'The maximum propagation speed is: (Knots)', max_speed) return mean_speed, max_speed
def degree(storm: list) -> list: ''' This function defines how to caluclate from text data to the time interval and distance interval between lines next to each other. :param storm: a list containing the whole information for a single strom. eg: list[0] :return: a list, a dataframe containing delta (unit: hour), delta_accu(unit:hour), dist(unit:meter), and dist_accu (unit:degree). ''' # time is not processed yet. de = [] dist_accu = 0 delta_accu = 0 for line in range(1, len(storm) - 1): c = time2(storm[line][0], storm[line][1]) d = time2(storm[line + 1][0], storm[line + 1][1]) delta1 = d - c delta_accu = d - time2(storm[1][0], storm[1][1]) # a = ev.LatLon(latlon(list[0][line][4]), latlon(list[0][line][5])) # b = ev.LatLon(latlon(list[0][line + 1][4]), latlon(list[0][line + 1][5])) a = ev.LatLon(storm[line][4], storm[line][5]) b = ev.LatLon(storm[line + 1][4], storm[line + 1][5]) if a != b: # ee = a.distanceTo3(b) # dist1=ee[0]; # degree1=ee[1]; dist1 = a.distanceTo(b) degree1 = a.bearingTo(b) dist_accu += dist1 #de.append([delta1, delta_accu, dist1, dist_accu, degree1, velocity]) de.append([ delta1.total_seconds() / 3600, delta_accu.total_seconds() / 3600, dist1, dist_accu, degree1, (dist1) / (delta1.total_seconds() / 3600) ]) #else: #print('same location') return de
def match_pair(driver, rider, interval, driver_prefer_time): # TODO: Calculate distance from the coordinations of riders and drivers... d1 = ev.LatLon(driver.start[1], driver.start[0]) r1 = ev.LatLon(rider.start[1], rider.start[0]) pickup_distance = d1.distanceTo(r1) * 0.00062137 #in miles pickup_time = pickup_distance * 7 pickup_slots = pickup_time / interval d2 = ev.LatLon(driver.destination[1], driver.destination[0]) r2 = ev.LatLon(rider.destination[1], rider.destination[0]) dropoff_distance = r2.distanceTo(d2) * 0.00062137 #in miles dropoff_time = dropoff_distance * 7 dropoff_slots = dropoff_time / interval driver_start_slot = driver.start_slot + pickup_slots driver_end_slot = driver.end_slot + pickup_slots driver_increase_slots = pickup_slots + dropoff_slots if driver_end_slot > rider.start_slot-1 and driver_start_slot-1 <= rider.end_slot \ and driver_increase_slots<=driver_prefer_time: return ('matched', pickup_time + dropoff_time) else: return 'unmatched'
def find_hurricanes_hitting_location(lat: float, lon: float) -> list: """ Find out those storms will hit the specific location assigned :param lat: float :param lon: float :param storms_profile: list :return: ['str', ...] """ dirname = os.path.dirname(__file__) dirname = Path(dirname) storms_profile = read_stroms_txt( str(dirname.parent) + '/data/atl.txt', str(dirname.parent) + '/data/pac.txt') assign_loc = ev.LatLon(lat, lon) hit_storm = [] for storm in storms_profile: qualify_storm = False for each_route in storm['route']: # print(each_route) latlon = ev.LatLon(each_route[4], each_route[5]) if meter_to_nm(latlon.distanceTo(assign_loc)) <= 5.0 and int( each_route[6]) >= 64: qualify_storm = True quadrant_index = int(latlon.distanceTo3(assign_loc)[-1] // 90) quadrant_distance = float(each_route[16:20][quadrant_index]) if meter_to_nm(quadrant_distance >= latlon.distanceTo(assign_loc)): qualify_storm = True if qualify_storm == True: hit_storm.append(storm['Name']) return hit_storm
def test_ll_to_osgr_to_ll(): # location on the Isles of Scilly lat = 49.926244 lon = -6.297934 ll_orig = eV.LatLon(lat, lon) osgr = toOsgr(ll_orig) ll_osgr = osgr.toLatLon(eV.LatLon) assert ll_orig.distanceTo(ll_osgr) < 1 parsed_osgr = parseOSGR(str(osgr)) ll_parsed_osgr = parsed_osgr.toLatLon(eV.LatLon) assert ll_orig.distanceTo(ll_parsed_osgr) < 1 osgr_new = Osgr(osgr.easting, osgr.northing) ll_osgr_new = osgr_new.toLatLon(eV.LatLon) assert ll_orig.distanceTo(ll_osgr) < 1
def get_bearing(): bear_sum = [] for j in range(count): Lat_sum1, Lont_sum1 = Lat_sums[j], Lont_sums[j] x = [] xs = [] x.append(ev.LatLon(Lat_sum1[0], Lont_sum1[0])) excep = x[0] for i in range(recordP_sum[j] - 1): # only one record or there are similar latitude and longitutude for two knots if recordP_sum[j] == 1 or (Lat_sum1[i] == Lat_sum1[i + 1] and Lont_sum1[i] == Lont_sum1[i + 1]): x.append(0) xs.append(0) else: x.append(ev.LatLon(Lat_sum1[i + 1], Lont_sum1[i + 1])) try: xs.append(excep.bearingTo(x[i + 1])) except AttributeError: print("there is something wrong here") excep = x[i + 1] bear_sum.append(xs) # find the previous one which is not 0. return bear_sum
def get_track_position(data: PositionRequest): distance = 0 old_location = None for _location in data.track: current_location = eV.LatLon(_location.lat, _location.lon) if old_location: segment_length, bearing = old_location.distanceTo3( current_location)[:2] if distance + segment_length >= data.distance: position = old_location.destination(data.distance - distance, bearing).latlon2(ndigits=6) return {'lat': position.lat, 'lon': position.lon} distance += segment_length old_location = current_location return {}
def get_height(self, lat, lon): if not (-90 <= lat <= 90 and -180 <= lon <= 180): raise ValueError('invalid coordinates ({}, {})'.format(lat, lon)) result = { 'altitude_m': self.NODATA, 'source': self.attribution_name, 'lat': lat, 'lon': lon, 'distance_m': 0, 'attributions': [self.attribution] } if lat < 49.7 or lat > 62 or lon < -10 or lon > 4: return result try: osgr = toOsgr(eV.LatLon(lat, lon)) if len(osgr.toStr()) == 0: raise ValueError('not a valid OSGR coordinate') except ValueError: return result # fit request to the grid osgr = osgr_to_grid(osgr) latlon = osgr.toLatLon(eV.LatLon) lat_found = latlon.lat lon_found = latlon.lon filename = get_filename(osgr) full_path = os.path.join(self.path, filename[:2].lower(), filename) if not os.path.isfile(full_path): return result x = get_x(osgr) y = get_y(osgr) with open(full_path, "rb") as f: # go to the right spot, f.seek((y * NCOLS + x) * 4) # read four bytes and convert them: buf = f.read(4) # ">f" is a four byte float val = struct.unpack('>f', buf)[0] result.update({ 'lat_found': round(lat_found, 6), 'lon_found': round(lon_found, 6), 'altitude_m': round(val, 2), 'distance_m': round(calculate_distance(lat, lon, lat_found, lon_found), 3) }) return result
def myLatLon(lat: str, lon: str): """Given a latitude and longitude, normalize them if necessary, to return a valid ellipsoidalVincenty.LatLon object. :param lat: the latitude as a string :param lon: the longitude as a string """ # get number portion: if lon[-1] in ['E', 'W']: lon_num = float(lon[:-1]) lon_dir = lon[-1] else: lon_num = float(lon) if lon_num > 180.0: # Does longitude exceed range? lon_num = 360.0 - lon_num lon_dir = flip_direction(lon_dir) lon = str(lon_num) + lon_dir return ev.LatLon(lat, lon)
def get_distance(list): """ Get a list whose elements are distances between each two adjacent samples, according to given latitude and longitude pairs. :param list: A list whose elements are sublists. Each sublist has two elements, latitude (string) and longitude (string). :return: distance: A list which elements are distances (nautical miles). """ loc = [] distance = [] for i in range(len(list)): loc.append(ev.LatLon(list[i][0], list[i][1])) for j in range( len(loc) - 1 ): # Only N-1 distances would be got if N pairs of latitude and longitude pairs are given if loc[j] != loc[j + 1]: d = loc[j].distanceTo(loc[j + 1]) / 1852.0 distance.append(d) else: distance.append(int(0)) return distance
def point(data: str): """ Find the lon & lat of a line of record. :param data: :return: """ lat = data.split(',')[4] lon = data.split(',')[5] # return ev.LatLon(point_n, point_w) if lon[-1] in ['E', 'W']: lon_num = float(lon[:-1]) lon_dir = lon[-1] else: lon_num = float(lon) if lon_num > 180.0: # Does longitude exceed range? lon_num = 360.0 - lon_num lon_dir = flip_direction(lon_dir) lon = str(lon_num) + lon_dir return ev.LatLon(lat, lon)
def distance_cal(locations): """ calculate the distance in nautical miles by longitude and the latitude :param locations: a list of nodes containing the longitude and the latitude of locations :return:total distance between locations """ if len(locations) == 1: t_dis = 0 else: node = [] i = 0 while i < len(locations): node.append(ev.LatLon(locations[i][0], locations[i][1])) i += 1 j = 0 temp_dis = [] while j < (len(locations) - 1): temp_dis.append(node[j].distanceTo(node[j + 1])) j += 1 t_dis = sum(temp_dis) / 1852.0 return t_dis
sphericalNvector.LatLon(50, -20) ] mean = sphericalNvector.meanOf(points) # XXX meanOf t.test(7, 'meanOf', mean.toStr(F_D, prec=4), '67.2362°N, 006.9175°W') # t.test(7, 'meanOfLatLon', mean.__class__, "<class 'sphericalNvector.LatLon'>") # ++ # Example 8: A and azimuth/distance to B a = sphericalNvector.LatLon(80, -90) b = a.destination(1000, 200) # JSname: destinationPoint t.test(8, 'destination(sphNv)', b.toStr(F_D), '79.991549°N, 090.017698°W') a = sphericalTrigonometry.LatLon(80, -90) # +++ b = a.destination(1000, 200) # JSname: destinationPoint t.test(8, 'destination(sphTy)', b.toStr(F_D), '79.991549°N, 090.017698°W') a = ellipsoidalVincenty.LatLon(80, -90) # +++ b = a.destination(1000, 200) t.test(8, 'destination(elVincenty)', b.toStr(F_D), '79.991584°N, 090.017621°W') # Example 9: Intersection of two paths a1 = sphericalNvector.LatLon(10, 20) a2 = sphericalNvector.LatLon(30, 40) b1 = sphericalNvector.LatLon(50, 60) b2 = sphericalNvector.LatLon(70, 80) c = sphericalNvector.intersection(a1, a2, b1, b2) t.test(9, 'intersection', c, '40.318643°N, 055.901868°E') # Example 10: Cross track distance a1 = sphericalNvector.LatLon(0, 0) a2 = sphericalNvector.LatLon(10, 0)
def parse_records(headline, records, range2true): total_distance = 0 propagation_sum = 0 max_propagation = 0 sub_count = 0 total_hour_difference = 0 if len(records) > 0: for i in range(len(records)): # last record, skip if i == len(records) - 1: break # get latitude and longitude cur_latitude = records[i].split(',')[4].strip() cur_longitude = records[i].split(',')[5].strip() print("cur_latitude") print(cur_latitude) print(cur_longitude) cur_position = ev.LatLon(cur_latitude, cur_longitude) next_latitude = records[i + 1].split(',')[4].strip() next_longitude = records[i + 1].split(',')[5].strip() next_position = ev.LatLon(next_latitude, next_longitude) # calculate distance distance = cur_position.distanceTo(next_position) / 1852.0 total_distance += distance # calculate speed day_difference = int(records[i + 1].split(',')[0].strip()) - int( records[i].split(',')[0].strip()) minute_difference = int( records[i + 1].split(',')[1].strip()) - int( records[i].split(',')[1].strip()) hour_difference = (day_difference * 2400 + minute_difference) / 100 speed = distance / hour_difference total_hour_difference += hour_difference propagation_sum += speed if speed > max_propagation: max_propagation = speed print(speed) # investigate scientific hypothesis bearing = cur_position.bearingTo(next_position) max_quadrant = [] flag = True # whether segment is eligible for j in range(2, -1, -1): # from 64, 50 to 34-kt start = 8 + j * 4 northeastern_extent = int(records[i].split(',')[start].strip()) southeastern_extent = int(records[i].split(',')[start + 1].strip()) southwestern_extent = int(records[i].split(',')[start + 2].strip()) northwestern_extent = int(records[i].split(',')[start + 3].strip()) if northeastern_extent == -999: # invalid flag = False break if northeastern_extent + southeastern_extent + southwestern_extent + northwestern_extent == 0: if j == 0: # no wind, not eligible segment flag = False continue else: # find expected quadrants max_extent = max(northeastern_extent, southeastern_extent, southwestern_extent, northwestern_extent) if northeastern_extent == max_extent: max_quadrant.append(1) if southeastern_extent == max_extent: max_quadrant.append(2) if southwestern_extent == max_extent: max_quadrant.append(3) if northwestern_extent == max_extent: max_quadrant.append(4) break if not flag: continue # eligible segment sub_count += 1 for k in range(70, 111): degree = (bearing + k) % 360 if 0 <= degree <= 90 and 1 in max_quadrant or 90 <= degree <= 180 and 2 in max_quadrant \ or 180 <= degree <= 270 and 3 in max_quadrant or (270 <= degree <= 359 or degree == 0) and 4 in max_quadrant: range2true[k] += 1 continue if total_hour_difference != 0: mean_speed = total_distance / total_hour_difference print(mean_speed) return sub_count