class GeodSharedMemoryBugTestIssue64(unittest.TestCase): def setUp(self): self.g = Geod(ellps='clrk66') self.ga = self.g.a self.mercury = Geod(a=2439700) # Mercury 2000 ellipsoid # Mercury is much smaller than earth. def test_not_shared_memory(self): self.assertEqual(self.ga, self.g.a) # mecury must have a different major axis from earth self.assertNotEqual(self.g.a, self.mercury.a) self.assertNotEqual(self.g.b, self.mercury.b) self.assertNotEqual(self.g.sphere, self.mercury.sphere) self.assertNotEqual(self.g.f, self.mercury.f) self.assertNotEqual(self.g.es, self.mercury.es) # initstrings were not shared in issue #64 self.assertNotEqual(self.g.initstring, self.mercury.initstring) def test_distances(self): # note calculated distance was not an issue with #64, but it still a shared memory test boston_lat = 42.+(15./60.); boston_lon = -71.-(7./60.) portland_lat = 45.+(31./60.); portland_lon = -123.-(41./60.) az12,az21,dist_g = self.g.inv(boston_lon,boston_lat,portland_lon,portland_lat) az12,az21,dist_mercury = self.mercury.inv(boston_lon,boston_lat,portland_lon,portland_lat) self.assertLess(dist_mercury, dist_g)
def __init__(self, wkt_polygon, **params): super().__init__(**params) # TODO: wkt.loads may cause QGIS crash!!! #if sys.platform == 'linux': # from shapely import wkt,geometry from shapely import wkt,geometry print("Original WKT:", wkt_polygon) self.poly = wkt.loads(wkt_polygon) #print("Before Orient:", self.poly.wkt) self.poly = geometry.polygon.orient(self.poly, 1.0) # print("After Orient:", self.poly.wkt) rect = self.poly.minimum_rotated_rectangle rect_coords = list(rect.exterior.coords) # 获取最佳包围矩形的三个点 p1 = rect_coords[0] p2 = rect_coords[1] p4 = rect_coords[3] # 分别计算第一个点到邻近两个点的距离 geod = Geod(ellps="WGS84") # distance1 代表与第二个点的距离,CCW angle1, backAngle1, distance1 = geod.inv(p1[0], p1[1], p2[0], p2[1]) # distance1 代表与第4个点的距离 angle2, backAngle2, distance2 = geod.inv(p1[0], p1[1], p4[0], p4[1]) #print(angle1, backAngle1, distance1) #print(angle2, backAngle2, distance2) angle1 = angle1 if angle1 > 0 else angle1 + 360 angle2 = angle2 if angle2 > 0 else angle2 + 360 #print(angle1, backAngle1, distance1) #print(angle2, backAngle2, distance2) # 确定使用哪个方向上的点为我所用 self.point_first = p1 self.point_final = p2 if distance1 > distance2 else p4 distance_final = distance1 if distance1 < distance2 else distance2 self.angle_final_added = 0 directionLeft = True if p1[0] < p2[0]: if distance2 > distance1: directionLeft = False else: directionLeft = True else: if distance2 > distance1: directionLeft = False else: directionLeft = True expand_count = int(distance_final / self.sidewiseline) self.leftExpand = expand_count if directionLeft is True else 0 self.rightExpand = expand_count if directionLeft is not True else 0
def deviations(lat1, lon1, lat2, lon2): """Desvíos entre lat1-lat2 y lon1-lon2 en metros.""" from pyproj import Geod g = Geod(ellps="GRS80") azi1, azi2, dLat = g.inv(lon1, lat1, lon1, lat2) dLat = -dLat if lat1 > lat2 else dLat azi1, azi2, dLon = g.inv(lon1, lat1, lon2, lat1) dLon = -dLon if lon1 > lon2 else dLon return dLat, dLon
def listener(): rospy.init_node('bot_yaw', 'bot_gps', anonymous=True, disable_signals=True) rospy.Subscriber("imu", Imu, callback) rospy.Subscriber("fix", NavSatFix, callback2) pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1) rate = rospy.Rate(10) # 10hz twist = Twist() while 1: geodesic = Geod(ellps='WGS84') bearing, reverse_bearing, dist = geodesic.inv(lon1, lat1, lon2, lat2) bearing = bearing + 180 angle_diff = yaw - bearing print("Yaw: ", yaw, "Bearing: ", bearing) print("Angle: ", angle_diff) if angle_diff > 1: if angle_diff < 180: twist.angular.z = 0.7 elif angle_diff > 180: twist.angular.z = -0.7 pub.publish(twist) elif angle_diff < -1: angle_diff = abs(angle_diff) if angle_diff < 180: twist.angular.z = -0.7 elif angle_diff > 180: twist.angular.z = 0.7 pub.publish(twist) if angle_diff < 1 and angle_diff > -1: break while 1: bearing, reverse_bearing, dist = geodesic.inv(lon1, lat1, lon2, lat2) if dist > 3: twist.linear.y = 0 twist.linear.z = 0 twist.angular.x = 0 twist.angular.y = 0 twist.angular.z = 0 twist.linear.x = -0.8 print("Distance: ", dist) pub.publish(twist) flag = 0 elif dist < 3: twist.linear.y = 0 twist.linear.z = 0 twist.angular.x = 0 twist.angular.y = 0 twist.angular.z = 0 twist.linear.x = 0 pub.publish(twist) rospy.spin()
def plot_contours(area, points, fig, ax, plot_legend=True, plot_points=True): geod = Geod(ellps='WGS84') xmin = area.bounds[0] xmax = area.bounds[2] ymin = area.bounds[1] ymax = area.bounds[3] X = np.linspace(xmin, xmax) Y = np.linspace(ymin, ymax) Z = np.zeros([len(Y), len(X)]) mindb = 60 maxdb = 180 N = int((maxdb - mindb) / 10) v = np.linspace(mindb, maxdb, N + 1) # generate contour volues with Shepard's Method for x in range(0, len(X)): for y in range(0, len(Y)): # sum of distances from this point to all points totaldist = sum( [geod.inv(X[x], Y[y], p[0], p[1])[2]**-8 for p in points]) Z[y, x] = min( maxdb, sum([ p[2] * (geod.inv(X[x], Y[y], p[0], p[1])[2]**-8) / totaldist for p in points ])) #CS = ax.contour(X,Y,Z,N, linewidth=0.5, colors='k', alpha=0.3) CSF = ax.contourf(X, Y, Z, N, cmap=plt.cm.RdYlGn_r, alpha=1, vmin=v[0], vmax=v[-1], levels=v) #vmin = min([p[2] for p in points]), vmax=max([p[2] for p in points])) if plot_legend: cb = fig.colorbar(CSF, ticks=v) cb.set_label("dB Loss") if plot_points: for p in points: print(p) ax.plot(p[0], p[1], '.', color='k', ms=4)
def test_geod_inverse_transform(): gg = Geod(ellps="clrk66") lat1pt = 42.0 + (15.0 / 60.0) lon1pt = -71.0 - (7.0 / 60.0) lat2pt = 45.0 + (31.0 / 60.0) lon2pt = -123.0 - (41.0 / 60.0) """ distance between boston and portland, clrk66: -66.531 75.654 4164192.708 distance between boston and portland, WGS84: -66.530 75.654 4164074.239 testing pickling of Geod instance distance between boston and portland, clrk66 (from pickle): -66.531 75.654 4164192.708 distance between boston and portland, WGS84 (from pickle): -66.530 75.654 4164074.239 inverse transform from proj.4 invgeod: b'-66.531\t75.654\t4164192.708\n' """ print("from pyproj.Geod.inv:") az12, az21, dist = gg.inv(lon1pt, lat1pt, lon2pt, lat2pt) assert_almost_equal((az12, az21, dist), (-66.531, 75.654, 4164192.708), decimal=3) print("forward transform") print("from proj.4 geod:") endlon, endlat, backaz = gg.fwd(lon1pt, lat1pt, az12, dist) assert_almost_equal((endlon, endlat, backaz), (-123.683, 45.517, 75.654), decimal=3) print("intermediate points:") print("from geod with +lat_1,+lon_1,+lat_2,+lon_2,+n_S:") npts = 4 lonlats = gg.npts(lon1pt, lat1pt, lon2pt, lat2pt, npts) lonprev = lon1pt latprev = lat1pt print(dist / (npts + 1)) print("%6.3f %7.3f" % (lat1pt, lon1pt)) result_dists = ( (-66.53059478766238, 106.79071710136431, 832838.5416198927), (-73.20928289863558, 99.32289055927389, 832838.5416198935), (-80.67710944072617, 91.36325611787134, 832838.5416198947), (-88.63674388212858, 83.32809401477382, 832838.5416198922), ) for (lon, lat), (res12, res21, resdist) in zip(lonlats, result_dists): az12, az21, dist = gg.inv(lonprev, latprev, lon, lat) assert_almost_equal((az12, az21, dist), (res12, res21, resdist)) latprev = lat lonprev = lon az12, az21, dist = gg.inv(lonprev, latprev, lon2pt, lat2pt) assert_almost_equal((lat2pt, lon2pt, dist), (45.517, -123.683, 832838.542), decimal=3)
def lonlat(lon, lat): from pyproj import Geod geo = Geod(ellps='WGS84') x = [np.min(lon), np.max(lon), np.min(lat), np.max(lat)] return { 'lon_0': .5 * np.sum(x[:2]), 'lat_0': .5 * np.sum(x[2:]), 'width': geo.inv(x[0], x[3], x[1], x[3])[2], 'height': geo.inv(x[0], x[2], x[0], x[3])[2], 'lat_1': -10, 'lat_2': -40 }
def lonlat_gradient(lon, lat, data): """ Calculate the 2D gradient of data on a regular lonlat grid. Parameters ---------- lon, lat : 1D array Coordinates of the regular grid (sizes N, M). data: 2D array Whose derivative is taken (size M, N). Returns ------- d_dx, d_dy, grad_norm: 2D array Gradients along lon and lat axes, and gradient norm (data units / m). """ # Call pyproj geod = Geod(ellps='WGS84') # Ensure the grid is regular dlons = np.unique(np.diff(lon)) dlats = np.unique(np.diff(lat)) if (dlons.size > 1) | (dlats.size > 1): msg = 'Grid not regular. dlons, dlats: ' raise ValueError(msg, dlons, dlats) # Make regularly spaced vectors around grid points _lon_bin = ps.binc2edge(lon) _lat_bin = ps.binc2edge(lat) # x spacing for each y value _, _, _dx = geod.inv(_lon_bin[0] * np.ones(lat.size), _lat_bin[:-1], _lon_bin[1] * np.ones(lat.size), _lat_bin[1:]) # y spacing for each x value _, _, _dy = geod.inv(_lon_bin[:-1], _lat_bin[0] * np.ones(lon.size), _lon_bin[1:], _lat_bin[1] * np.ones(lon.size)) # Convert to m dy, dx = np.meshgrid(_dy, _dx) # Calculate gradient assuming dlon = dlat = 1 diff_y, diff_x = np.gradient(data) # Divide each gradient grid point by the represented distance d_dx = diff_x / dx d_dy = diff_y / dy # Calculate the norm of the gradient norm = np.sqrt(d_dx**2 + d_dy**2) return d_dx, d_dy, norm
def lat_lon_grid_deltas(longitude, latitude, **kwargs): r"""Calculate the delta between grid points that are in a latitude/longitude format. Calculate the signed delta distance between grid points when the grid spacing is defined by delta lat/lon rather than delta x/y Parameters ---------- longitude : array_like array of longitudes defining the grid latitude : array_like array of latitudes defining the grid kwargs Other keyword arguments to pass to :class:`~pyproj.Geod` Returns ------- dx, dy: at least two dimensional arrays of signed deltas between grid points in the x and y direction Notes ----- Accepts 1D, 2D, or higher arrays for latitude and longitude Assumes [..., Y, X] for >=2 dimensional arrays """ from pyproj import Geod # Inputs must be the same number of dimensions if latitude.ndim != longitude.ndim: raise ValueError( 'Latitude and longitude must have the same number of dimensions.') # If we were given 1D arrays, make a mesh grid if latitude.ndim < 2: longitude, latitude = np.meshgrid(longitude, latitude) geod_args = {'ellps': 'sphere'} if kwargs: geod_args = kwargs g = Geod(**geod_args) forward_az, _, dy = g.inv(longitude[..., :-1, :], latitude[..., :-1, :], longitude[..., 1:, :], latitude[..., 1:, :]) dy[(forward_az < -90.) | (forward_az > 90.)] *= -1 forward_az, _, dx = g.inv(longitude[..., :, :-1], latitude[..., :, :-1], longitude[..., :, 1:], latitude[..., :, 1:]) dx[(forward_az < 0.) | (forward_az > 180.)] *= -1 return dx * units.meter, dy * units.meter
def test_geod_cities(): # specify the lat/lons of some cities. boston_lat = 42.0 + (15.0 / 60.0) boston_lon = -71.0 - (7.0 / 60.0) portland_lat = 45.0 + (31.0 / 60.0) portland_lon = -123.0 - (41.0 / 60.0) g1 = Geod(ellps="clrk66") g2 = Geod(ellps="WGS84") az12, az21, dist = g1.inv(boston_lon, boston_lat, portland_lon, portland_lat) print("distance between boston and portland, clrk66:") print("%7.3f %6.3f %12.3f" % (az12, az21, dist)) assert_almost_equal((az12, az21, dist), (-66.531, 75.654, 4164192.708), decimal=3) print("distance between boston and portland, WGS84:") az12, az21, dist = g2.inv(boston_lon, boston_lat, portland_lon, portland_lat) assert_almost_equal((az12, az21, dist), (-66.530, 75.654, 4164074.239), decimal=3) print("%7.3f %6.3f %12.3f" % (az12, az21, dist)) print("testing pickling of Geod instance") with temporary_directory() as tmpdir: with open(os.path.join(tmpdir, "geod1.pickle"), "wb") as gp1w: pickle.dump(g1, gp1w, -1) with open(os.path.join(tmpdir, "geod2.pickle"), "wb") as gp2w: pickle.dump(g2, gp2w, -1) with open(os.path.join(tmpdir, "geod1.pickle"), "rb") as gp1: g3 = pickle.load(gp1) with open(os.path.join(tmpdir, "geod2.pickle"), "rb") as gp2: g4 = pickle.load(gp2) az12, az21, dist = g3.inv(boston_lon, boston_lat, portland_lon, portland_lat) assert_almost_equal((az12, az21, dist), (-66.531, 75.654, 4164192.708), decimal=3) print("distance between boston and portland, clrk66 (from pickle):") print("%7.3f %6.3f %12.3f" % (az12, az21, dist)) az12, az21, dist = g4.inv(boston_lon, boston_lat, portland_lon, portland_lat) print("distance between boston and portland, WGS84 (from pickle):") print("%7.3f %6.3f %12.3f" % (az12, az21, dist)) assert_almost_equal((az12, az21, dist), (-66.530, 75.654, 4164074.239), decimal=3) g3 = Geod("+ellps=clrk66") # proj4 style init string print("inverse transform") lat1pt = 42.0 + (15.0 / 60.0) lon1pt = -71.0 - (7.0 / 60.0) lat2pt = 45.0 + (31.0 / 60.0) lon2pt = -123.0 - (41.0 / 60.0) az12, az21, dist = g3.inv(lon1pt, lat1pt, lon2pt, lat2pt) print("%7.3f %6.3f %12.3f" % (az12, az21, dist)) assert_almost_equal((az12, az21, dist), (-66.531, 75.654, 4164192.708), decimal=3)
def test_geod_inverse_transform(): gg = Geod(ellps="clrk66") lat1pt = 42.0 + (15.0 / 60.0) lon1pt = -71.0 - (7.0 / 60.0) lat2pt = 45.0 + (31.0 / 60.0) lon2pt = -123.0 - (41.0 / 60.0) """ distance between boston and portland, clrk66: -66.531 75.654 4164192.708 distance between boston and portland, WGS84: -66.530 75.654 4164074.239 testing pickling of Geod instance distance between boston and portland, clrk66 (from pickle): -66.531 75.654 4164192.708 distance between boston and portland, WGS84 (from pickle): -66.530 75.654 4164074.239 inverse transform from proj.4 invgeod: b'-66.531\t75.654\t4164192.708\n' """ print("from pyproj.Geod.inv:") az12, az21, dist = gg.inv(lon1pt, lat1pt, lon2pt, lat2pt) assert_almost_equal((az12, az21, dist), (-66.531, 75.654, 4164192.708), decimal=3) print("forward transform") print("from proj.4 geod:") endlon, endlat, backaz = gg.fwd(lon1pt, lat1pt, az12, dist) assert_almost_equal((endlon, endlat, backaz), (-123.683, 45.517, 75.654), decimal=3) print("intermediate points:") print("from geod with +lat_1,+lon_1,+lat_2,+lon_2,+n_S:") npts = 4 lonlats = gg.npts(lon1pt, lat1pt, lon2pt, lat2pt, npts) lonprev = lon1pt latprev = lat1pt print(dist / (npts + 1)) print("%6.3f %7.3f" % (lat1pt, lon1pt)) result_dists = ( (-66.53059478766238, 106.79071710136431, 832838.5416198927), (-73.20928289863558, 99.32289055927389, 832838.5416198935), (-80.67710944072617, 91.36325611787134, 832838.5416198947), (-88.63674388212858, 83.32809401477382, 832838.5416198922), ) for (lon, lat), (res12, res21, resdist) in zip(lonlats, result_dists): az12, az21, dist = gg.inv(lonprev, latprev, lon, lat) assert_almost_equal((az12, az21, dist), (res12, res21, resdist)) latprev = lat lonprev = lon az12, az21, dist = gg.inv(lonprev, latprev, lon2pt, lat2pt) assert_almost_equal( (lat2pt, lon2pt, dist), (45.517, -123.683, 832838.542), decimal=3 )
def calc_dx_dy(lon, lat, shape='WGS84', radius=6370997.): """ This definition calculates the distance between grid points that are in a latitude/longitude format. Using pyproj GEOD; different Earth Shapes https://jswhit.github.io/pyproj/pyproj.Geod-class.html Common shapes: 'sphere', 'WGS84', 'GRS80' :param lon: 1D or 2D longitude array. :param lat: 1D or 2D latitude array. :param shape: earth shape. :param radius: earth radius. :return: dx, dy; 2D arrays of distances between grid points in the x and y direction in meters :Example: >>> lat = np.arange(90,-0.1,-0.5) >>> lon = np.arange(0,360.1,0.5) >>> dx, dy = calc_dx_dy(lon, lat) """ # check longitude and latitude if lon.ndim == 1: longitude, latitude = np.meshgrid(lon, lat) else: longitude = lon latitude = lat if radius != 6370997.: gg = Geod(a=radius, b=radius) else: gg = Geod(ellps=shape) dx = np.empty(latitude.shape) dy = np.zeros(longitude.shape) for i in range(latitude.shape[1]): for j in range(latitude.shape[0] - 1): _, _, dx[j, i] = gg.inv( longitude[j, i], latitude[j, i], longitude[j + 1, i], latitude[j + 1, i]) dx[j + 1, :] = dx[j, :] for i in range(latitude.shape[1] - 1): for j in range(latitude.shape[0]): _, _, dy[j, i] = gg.inv( longitude[j, i], latitude[j, i], longitude[j, i + 1], latitude[j, i + 1]) dy[:, i + 1] = dy[:, i] return dx, dy
def lat_lon_grid_deltas(longitude, latitude, **kwargs): r"""Calculate the delta between grid points that are in a latitude/longitude format. Calculate the signed delta distance between grid points when the grid spacing is defined by delta lat/lon rather than delta x/y Parameters ---------- longitude : array_like array of longitudes defining the grid latitude : array_like array of latitudes defining the grid kwargs Other keyword arguments to pass to :class:`~pyproj.Geod` Returns ------- dx, dy: at least two dimensional arrays of signed deltas between grid points in the x and y direction Notes ----- Accepts 1D, 2D, or higher arrays for latitude and longitude Assumes [..., Y, X] for >=2 dimensional arrays """ from pyproj import Geod # Inputs must be the same number of dimensions if latitude.ndim != longitude.ndim: raise ValueError('Latitude and longitude must have the same number of dimensions.') # If we were given 1D arrays, make a mesh grid if latitude.ndim < 2: longitude, latitude = np.meshgrid(longitude, latitude) geod_args = {'ellps': 'sphere'} if kwargs: geod_args = kwargs g = Geod(**geod_args) forward_az, _, dy = g.inv(longitude[..., :-1, :], latitude[..., :-1, :], longitude[..., 1:, :], latitude[..., 1:, :]) dy[(forward_az < -90.) | (forward_az > 90.)] *= -1 forward_az, _, dx = g.inv(longitude[..., :, :-1], latitude[..., :, :-1], longitude[..., :, 1:], latitude[..., :, 1:]) dx[(forward_az < 0.) | (forward_az > 180.)] *= -1 return dx * units.meter, dy * units.meter
def get_wgs84_area(self, pixel=False): if Geod is not None: g = Geod(ellps='WGS84') extent = self.get_raster_extent(4326) ul = extent[0] ur = extent[1] lr = extent[2] _, _, width = g.inv(ul[0], ul[1], ur[0], ur[1]) _, _, height = g.inv(ur[0], ur[1], lr[0], lr[1]) area = width * height if pixel: return area / (self.cols * self.rows) else: return area
def build_bins(pts, spacing=6.25, width=50, runin=0, isequence0=1000, ellps='WGS84'): """ Build bins along a line of points. """ gd = Geod(ellps=ellps) div_pts = divide_line(pts, spacing=spacing, runin=runin, ellps=ellps) bins = [] ndiv = len(div_pts) ibin = isequence0 align_to_last_bin = False for i in range(0, ndiv - 1): lon0, lat0, x0, i0 = div_pts[i] lon1, lat1, x1, i1 = div_pts[i + 1] faz, baz, dist = gd.inv(lon0, lat0, lon1, lat1) # bin corners _bin = _build_bin(lon0, lat0, lon1, lat1, width, gd) # bin center _center = _calculate_center(_bin) # put it all together bins.append([ibin, None, _center, _bin]) # handle bends in the line if align_to_last_bin: # align bins bins[-1][3][0] = bins[-2][3][1] bins[-1][3][3] = bins[-2][3][2] # recalculate center and offset bins[-1][2] = _calculate_center(bins[-1][3]) align_to_last_bin = False if i0 == i1: ibin -= 1 i += 1 _bin = bins[-1] del bins[-1] align_to_last_bin = True # distance on line and line azimuth if i == 0: bins[-1][1] = div_pts[0][2] bins[-1] += [None] else: az, _, dx = gd.inv(bins[-1][2][0], bins[-1][2][1], bins[-2][2][0], bins[-2][2][1]) bins[-1][1] = bins[-2][1] + dx bins[-1] += [az] # increment bin number ibin += 1 # assume first azimuth is the same as 2nd azimuth bins[0][4] = [bins[1][4]] return bins
class GeodeticPath: """Calculate the geodetic path between two points using pyproj Geod""" def __init__(self, lon0, lat0, lon1, lat1, ellps='WGS84', radians=False): """Initialize with the start and stop points.""" self.geod = Geod(ellps=ellps) self.lon0 = lon0 self.lat0 = lat0 self.lon1 = lon1 self.lat1 = lat1 # Get the forward and backward azimuths and distance between the two points self.azimuth0, self.back_azimuth1, self.distance = self.geod.inv( lon0, lat0, lon1, lat1) def get_path_lonlats(self, separation): """Get the latitude and longitude of the path points, given a point separation in meters.""" self.npts = int(self.distance / separation + 0.5) self.lonlats = np.array( self.geod.npts(self.lon0, self.lat0, self.lon1, self.lat1, self.npts)) self.lon = self.lonlats[:, 0] self.lat = self.lonlats[:, 1] def get_path(self, separation=None): """Get the path latitude, longitude, heading, and distance. If separation is None, assume get_path_lon_lats has already been called.""" if separation != None: self.get_path_lonlats(separation) # Declare heading and distance arrays self.heading = np.zeros(len(self.lat), dtype=self.lat.dtype) self.along_track_distance = np.zeros(len(self.lat), dtype=self.lat.dtype) for i in range(len(self.lat) - 1): self.heading[i], back_azimuth, d = self.geod.inv( self.lon[i], self.lat[i], self.lon[i + 1], self.lat[i + 1]) self.along_track_distance[i + 1] = self.along_track_distance[i] + d if back_azimuth < 0: self.heading[-1] = 180 + back_azimuth else: self.heading[-1] = back_azimuth - 180.
def compute_route(graph, track_corr, edge_ids): ''' This function compute the resulting route of the map matched track. Parameters: ____________ graph: OSMNX road network Osmnx road network of the area of study track_corr: np.array array of projected coodinates of the floating car track points edge_ids: np.array Array of road segments corresponding to the floating car track points Returns: ___________ route: resulting route of the map matched track ''' # define the reference system geod = Geod(ellps='WGS84') # Compute the route coordinates route = [] path_length = [] unlinked = [] # find the route to the last point of the projected point for i in range(len(track_corr) - 1): if edge_ids[i] != edge_ids[i + 1]: # add the point to the route route.append(track_corr[i]) route.append([ graph.graph[edge_ids[i][1]][0][0], graph.graph[edge_ids[i][1]][0][1] ]) _, _, distance = geod.inv(track_corr[i][1], track_corr[i][0], graph.graph[edge_ids[i][1]][0][1], graph.graph[edge_ids[i][1]][0][0]) path_length.append(distance) unlinked.append(0) else: route.append(track_corr[i]) _, _, distance = geod.inv(track_corr[i][1], track_corr[i][0], track_corr[i + 1][1], track_corr[i + 1][0]) path_length.append(distance) unlinked.append(0) # Let's not forget the last point # route.append(track_corr[-1]) route = np.array(route) return route
def get_abi_pixel_lengths(dataset): """ Returns the length scales in x and y of each pixel in the input dataset """ g = Geod(ellps='WGS84') lat, lon = get_abi_lat_lon(dataset) dy, dx = np.zeros(lat.shape, dtype=float), np.zeros(lat.shape, dtype=float) dy[:-1] = g.inv(lon[:-1], lat[:-1], lon[1:], lat[1:])[-1] / 1e3 dx[:, :-1] = g.inv(lon[:, :-1], lat[:, :-1], lon[:, 1:], lat[:, 1:])[-1] / 1e3 dy[1:] += dy[:-1] dy[1:-1] /= 2 dx[:, 1:] += dx[:, :-1] dx[:, 1:-1] /= 2 return dx, dy
def run_geod(lat0, lon0, lat1, lon1): #global UNITS, ELLIPSOID #lat0 = deg2dms (lat0) #lon0 = deg2dms (lon0) #lat1 = deg2dms (lat1) #lon1 = deg2dms (lon1) ELLIPSOID = 'WGS84' UNITS = 'm' flds = [] config = "+ellps={0}".format(ELLIPSOID) g = Geod(config) az, baz, dist = g.inv(lon0, lat0, lon1, lat1) if dist: dist /= FACTS[UNITS] #command = "%s +ellps=%s -f \"%%.6f\" <<EOF -I +units=%s\n%s %s %s %s\nEOF" % (GEOD, ELLIPSOID, UNITS, lat0, lon0, lat1, lon1) #print command #try : #fh = os.popen (command) #while 1 : #line = fh.readline () #if not line : break #flds = line.split () ##print flds #except Exception, e : #sys.stderr.write ("Error: failed to execute:\n%s" % command) #flds = None # Return list containing azimuth, back azimuth, distance return az, baz, dist
def gdlComp(self, lons_lats, km_pts=20): """ Compute geodesic line lons_lats: input coordinates. (start longitude, start latitude, end longitude, end latitude) km_pts: compute one point each 20 km (default). """ try: lon_1, lat_1, lon_2, lat_2 = lons_lats pygd = Geod(ellps='WGS84') res = pygd.inv(lon_1, lat_1, lon_2, lat_2) dist = res[2] pts = int(math.ceil(dist) / (km_pts * 1000)) coords = pygd.npts(lon_1, lat_1, lon_2, lat_2, pts) coords_se = [(lon_1, lat_1)] + coords coords_se.append((lon_2, lat_2)) self.__logger.info("Geodesic line succesfully created!") self.__logger.info("Total points = {:,}".format(pts)) self.__logger.info("{:,.4f} km".format(dist / 1000.)) return coords_se except Exception as e: self.__logger.error("Error: {0}".format(e.message))
def calcEdgeLengths(nxG): '''Calculate the lengths of edges based on lat/lon position''' G = Geod(ellps='WGS84') for edge in nx.edges(nxG): nxG[edge[0]][edge[1]]['length'] = G.inv( nxG.nodes[edge[0]]['pos'][1], nxG.nodes[edge[0]]['pos'][0], nxG.nodes[edge[1]]['pos'][1], nxG.nodes[edge[1]]['pos'][0])[2]
def c1ompare_points_old(a, b, dx, proj='LongLat'): if isinstance(dx, float): dx = [dx, dx] tolerance = [0.6 * x for x in dx] if (proj == 'horizontal'): pa = project(a, projection_type='proj_cartesian') pb = project(b, projection_type='proj_cartesian') #print tolerance, pa, pb if ( not (abs(pa[1] - pb[1]) < tolerance[1]) ): return False elif (abs(pa[0] - pb[0]) < tolerance[0]): return True else: return False else: from pyproj import Geod wgs84_geod = Geod(ellps='WGS84') az12,az21,dist = wgs84_geod.inv(a[0],a[1],a[0],a[1]) return dist < tolerance[0] * 1e5 if ( not (abs(a[1] - b[1]) < tolerance[1]) ): #AddComment('lat differ') return False elif (abs(a[0] - b[0]) < tolerance[0]): #AddComment('long same') return True elif ((abs(abs(a[0]) - 180) < tolerance[0]) and (abs(abs(b[0]) - 180) < tolerance[0])): #AddComment('long +/-180') return True else: #AddComment('not same %g %g' % (abs(abs(a[0]) - 180), abs(abs(b[0]) - 180) ) ) return False
def get_distance_to_hypo(self,fault): ''' Get straight line distance from subfault center to hypocenter ''' from numpy import argmin,size,ones from pyproj import Geod #Projection object for distances p=Geod(ellps='WGS84') #Firs find the coordiantes of the hypocenter time_start=fault[:,7] i=argmin(time_start) if size(i)>1: #Hypocenter is ambiguos 'ERROR: Too many possible hypocenters' else: hypo=fault[i,0:3] # get horizontal distances az,baz,dist_h=p.inv(ones(len(fault))*hypo[1],ones(len(fault))*hypo[0],fault[:,1],fault[:,0]) dist_h=dist_h/1000. #vertical dsitances dist_v=abs(ones(len(fault))*hypo[2]-fault[:,2]) #total distance distance=(dist_h**2+dist_v**2)**0.5 return distance
def __init__(self, srs, bbox, width=None, height=None, format=None, resource_id=None): super(WmsQuery, self).__init__() self.query_type = 'WMS' self.srs = srs self.bbox = bbox self.width = width self.height = height self.format = format self.resource_id = resource_id if width is not None and height is not None: # calculate resolution... this should slow things down, yay... :-( p = Proj(init=srs.lower()) if not p.is_latlong(): min_lon, min_lat = p(bbox.min_x,bbox.min_y, inverse=True) max_lon, max_lat = p(bbox.max_x,bbox.max_y, inverse=True) else: min_lon, min_lat = bbox.min_x, bbox.min_y max_lon, max_lat = bbox.max_x, bbox.max_y g = Geod(ellps='clrk66') # Use Clarke 1966 ellipsoid. _,_,diagonal = g.inv(min_lon, min_lat, max_lon, max_lat) # distance calculated geodesic dist_x = sqrt(diagonal**2 / (1 + float(height)/float(width)) ) dist_y = dist_x * (float(height)/float(width)) self.x_res = dist_x / float(width) self.y_res = dist_y / float(height) else: self.x_res = None self.y_res = None
def compute_lagdistances(sta,stnum,lon,lat): ''' Compute the lag distances between all stations in the given set Input: sta: Array with strings of station names (n x 1) stnum: Array with unique station numbers (n x 1) lon: Array with station longitudes (n x 1) lat: Array with station latitudes (n x 1) Output: lagdistance: Upper triangular matrix with lag distances for all station pairs (n x n) ''' from pyproj import Geod import numpy as np # Make projection: p = Geod(ellps='WGS84') # Make lag matrix: lagdistance_full = np.zeros((len(stnum),len(stnum))) ## Start to fill in lag matrix # Loop over all stations, make a matrix with the lon and lat of just that station, and compute the distance to all other stations (lon,lat): for stationi in range(len(stnum)): azimuthi,backazimuthi,distancei = p.inv(lon[stationi]*np.ones(len(stnum)),lat[stationi]*np.ones(len(stnum)), lon, lat) # Fill the matrix with these distances for this station: lagdistance_full[stationi,:] = distancei/1000 # Turn it into an upper triangular matrix: lagdistance = np.triu(lagdistance_full) # Return lag distance: return lagdistance
def calculate_distances(d): g = Geod(ellps='WGS84') far_left_lat = d['elevation_latlon_list'][0][0] far_left_lon = d['elevation_latlon_list'][1][0] for i, v in d['twod_vertices'].iteritems(): pt_lat = v[0] pt_lon = v[1] az1, az2, dist = g.inv(far_left_lon, far_left_lat, pt_lon, pt_lat) km_dist = dist / 1000.0 d['twod_vertices'][i] = [v[0], v[1], v[2], km_dist] d['gps_dist'] = [] for pt_lat, pt_lon in zip(d['gps_lat'], d['gps_lon']): az1, az2, dist = g.inv(far_left_lon, far_left_lat, pt_lon, pt_lat) km_dist = dist / 1000.0 d['gps_dist'].append(km_dist)
def distance_matrix(pts, lon='lon', lat='lat', ellps='WGS84'): """ Calculate distance between all points Parameters ---------- pts: pandas.DataFrame Table of points with at least the collumns given by ``lon`` and ``lat`` lon, lat: str, optional Column names for the longitude and latitude fields. Defaults are 'lon' and 'lat'. ellps: str, optional Name of the ellipsoid. See :class:`pyproj.Geod` for valid names. Returns ------- distances: numpy.ndarray len(pts) x len(pts) array of distances between all points in ``pts``. """ gd = Geod(ellps=ellps) npts = len(pts) G = np.zeros((npts, npts)) for i in range(npts): for j in range(npts): _, _, G[i][j] = gd.inv(pts.ix[i][lon], pts.ix[i][lat], pts.ix[j][lon], pts.ix[j][lat]) return G
def compute_wg84_line_length(input_geom): """ Compute the length of a wg84 line (LineString and MultiLineString) :param input_geom: input geometry :type input_geom: shapely.geometry.LineString or shapely.geometry.MultiLineString :return: the line length :rtype: float """ total_length = 0 if input_geom.geom_type == "MultiLineString": for geom_line in input_geom.geoms: total_length += compute_wg84_line_length(geom_line) elif input_geom.geom_type == "LineString": coordinates_pairs = list(zip(input_geom.coords, input_geom.coords[1:])) for pair in coordinates_pairs: if len(pair[0]) == 3 or len(pair[1]) == 3: coords = pair[0][:-1] + pair[1][:-1] # avoid to catch the elevation coord else: coords = pair[0] + pair[1] wgs84_geod = Geod(ellps='WGS84') _, _, length_computed = wgs84_geod.inv(*coords) total_length += length_computed return total_length
def grcrcl1(lon_1, lat_1, lon_2, lat_2): g = Geod(ellps='WGS84') az, az_inv, dist = g.inv(lon_1, lat_1, lon_2, lat_2) return dist
def getAzimuth(self, point): """ Get azimuth (in degrees) between current point and provided point (point). """ g = Geod(ellps="sphere") forward_azimuth, back_azimuth, distance = g.inv(self.longitude, self.latitude, point.longitude, point.latitude) return forward_azimuth
def test_geod_inv_honours_input_types(lons1, lats1, lons2): # 622 gg = Geod(ellps="clrk66") outx, outy, outz = gg.inv(lons1=lons1, lats1=lats1, lons2=lons2, lats2=0) assert isinstance(outx, type(lons1)) assert isinstance(outy, type(lats1)) assert isinstance(outz, type(lons2))
def find_closest_soundings(l1b_file, tgt_latitude, tgt_longitude, max_distance, log_output=sys.stdout): l1b_obj = acos_file.L1B(l1b_file) sounding_ids = l1b_obj.get_sounding_ids() # Average over band first since this is likely to be consistent for # different types of L1B files latitudes = l1b_obj.get_sounding_info('sounding_latitude') longitudes = l1b_obj.get_sounding_info('sounding_longitude') # Average over any non sounding id sized dimensions while len(latitudes.shape) > 1: extra_dims = numpy.where(numpy.array(latitudes.shape) != sounding_ids.shape[0]) latitudes = numpy.average(latitudes, extra_dims[0][0]) longitudes = numpy.average(longitudes, extra_dims[0][0]) g = Geod(ellps='WGS84') # Find all distances in file distances = numpy.zeros(len(sounding_ids), dtype=float) for dist_idx, lat_lon_tuple in enumerate(zip(latitudes, longitudes)): curr_lat, curr_lon = lat_lon_tuple az12, az21, dist = g.inv(tgt_longitude,tgt_latitude,curr_lon,curr_lat) # Convert to km distances[dist_idx] = dist/1000. closest = numpy.where(distances <= max_distance) if len(closest[0]) > 0: print >>log_output, "%s" % l1b_file for close_idx in closest[0]: print >>log_output, '%d %f' % (sounding_ids[close_idx], distances[close_idx]) print >>log_output, "" else: print >>sys.stderr, "No soundings found in %s closer than %f km" % (l1b_file, max_distance)
def compute_rhyp(stlon,stlat,stelv,hypolon,hypolat,hypodepth): ''' Compute the hypocentral distance for a given station lon, lat and event hypo Input: stlon: Float with the station/site longitude stlat: Float with the station/site latitude stelv: Float with the station/site elevation (km) hypolon: Float with the hypocentral longitude hypolat: Float with the hypocentral latitude hypodepth: Float with the hypocentral depth (km) Output: rhyp: Float with the hypocentral distance, in km ''' import numpy as np from pyproj import Geod ## Make the projection: p = Geod(ellps='WGS84') ## Apply the projection to get azimuth, backazimuth, distance (in meters): az,backaz,horizontal_distance = p.inv(stlon,stlat,hypolon,hypolat) ## Put them into kilometers: horizontal_distance = horizontal_distance/1000. stelv = stelv/1000 ## Hypo deptha lready in km, but it's positive down. ST elevation is positive ## up, so make hypo negative down (so the subtraction works out): hypodepth = hypodepth * -1 ## Get the distance between them: rhyp = np.sqrt(horizontal_distance**2 + (stelv - hypodepth)**2) return rhyp
def lonlat2distances(lon, lat, meters_per_unit=1, **kwargs): """ Get distance between points of a GPS track. Distances are returned in meters by default. This can be adjusted by setting the `meters_per_unit` parameter (e.g. 1000 for km). Parameters ---------- lon, lat : 1D array Plate carree coordinates to process. meters_per_unit : float Number of meters in the desired output unit of distance. kwargs : keyword arguments Passed to `pyroj.Geod` . Returns ------- distances : 1D array Separating the input coordinates. """ kwargs = {'ellps': 'WGS84', **kwargs} _geod = Geod(**kwargs) distances = np.array([ _geod.inv(lon1, lat1, lon2, lat2) for (lon1, lat1, lon2, lat2) in zip(lon[:-1], lat[:-1], lon[1:], lat[1:]) ])[:, 2] distances /= meters_per_unit return distances
def compute_repi(stlon,stlat,hypolon,hypolat): ''' Compute the hypocentral distance for a given station lon, lat and event hypo Input: stlon: Float with the station/site longitude stlat: Float with the station/site latitude hypolon: Float with the hypocentral longitude hypolat: Float with the hypocentral latitude Output: repi: Float with the epicentral distance, in km ''' from pyproj import Geod ## Make the projection: p = Geod(ellps='WGS84') ## Apply the projection to get azimuth, backazimuth, distance (in meters): az,backaz,horizontal_distance = p.inv(stlon,stlat,hypolon,hypolat) ## Put them into kilometers: horizontal_distance = horizontal_distance/1000. ## Epicentral distance is horizontal distance: repi = horizontal_distance return repi
def lonlat2distancefrom(lon, lat, lon_0, lat_0, meters_per_unit=1, **kwargs): """ Get distance between GPS track and a fixed coordinate. Distances are returned in meters by default. This can be adjusted by setting the `meters_per_unit` parameter (e.g. 1000 for km). Parameters ---------- lon, lat : 1D array Plate carree coordinates of GPS track. lon_0, lat_0 : 1D array Plate carree coordinates of fixed coordinate. meters_per_unit : float Number of meters in the desired output unit of distance. kwargs : keyword arguments Passed to `pyroj.Geod` . Returns ------- distances : 1D array Separating the input coordinates. """ kwargs = {'ellps': 'WGS84', **kwargs} _geod = Geod(**kwargs) distances = np.array([ _geod.inv(lon_, lat_, lon_0, lat_0) for (lon_, lat_) in zip(lon, lat) ])[:, 2] distances /= meters_per_unit return distances
def arrivals(hypocenter, station_lon, station_lat): ''' Get P and S arrival times ''' from obspy.taup import TauPyModel from pyproj import Geod from numpy import rad2deg #Station to hypo distance g = Geod(ellps='WGS84') az, baz, dist = g.inv(hypocenter[0], hypocenter[1], station_lon, station_lat) #Convert distance from m to degrees and km dist_deg = rad2deg(dist / 6371e3) print dist / 1000 #Calculate theoretical arrivals mod = TauPyModel(model='Nocal') arrivals = mod.get_travel_times(source_depth_in_km=hypocenter[2], distance_in_degree=dist_deg, phase_list=('P', 'p', 'S', 's')) print arrivals #Parse arrivals ptime = 1e6 stime = 1e6 for k in range(len(arrivals)): if arrivals[k].name == 'p' or arrivals[k].name == 'P': ptime = min(arrivals[k].time, ptime) if arrivals[k].name == 's' or arrivals[k].name == 'S': stime = min(arrivals[k].time, stime) print ptime return ptime, stime
def lonlat2heading(lon, lat, **kwargs): """ Get forward azimuth from GPS track. Parameters ---------- lon, lat : 1D array Plate carree coordinates to process. Length m. kwargs : keyword arguments Passed to `pyroj.Geod` . Returns ------- heading : 1D array Forward azimuth. Length m-1. """ kwargs = {'ellps': 'WGS84', **kwargs} _geod = Geod(**kwargs) heading = np.array([ _geod.inv(lon1, lat1, lon2, lat2) for (lon1, lat1, lon2, lat2) in zip(lon[:-1], lat[:-1], lon[1:], lat[1:]) ])[:, 0] return heading
def pyproj_distance(x1, y1, x2, y2, ellipsoid_name): """ Compute geodesic using pyproj package :param x1: :param y1: :param x2: :param y2: :param ellipsoid_name: name of ellipsoid :return: distance (in m) """ geod = Geod(ellps=ellipsoid_name.upper()) if np.size(x1) != np.size(x2): try: if np.size(x1) < np.size(x2): x1 = np.full(x2.shape, x1) y1 = np.full(x2.shape, y1) else: x2 = np.full(x1.shape, x2) y2 = np.full(x1.shape, y2) except ValueError: raise ValueError( "x1/y1 and x2/y2 must have the same size or one pair must be scalar" ) return geod.inv(x1, y1, x2, y2)[2]
def distMatrix(inCoords, distanceMetric=False): """ Compute distance matrix between points coords : nparray shape[nPoints,2], with first column X, and Y. Proj 4326(WGS84) Return matrix of distance matrix between points. """ if distanceMetric: from pyproj import Geod geod = Geod(ellps='WGS84') distArray = np.zeros((len(inCoords), len(inCoords))) for n, p in enumerate( np.nditer(inCoords.T.copy(), flags=['external_loop'], order='F')): for i in range(len(inCoords)): x1, y1 = p x2, y2 = inCoords[i] angle1, angle2, dist = geod.inv(x1, y1, x2, y2) distArray[n, i] = dist else: from scipy.spatial import distance distArray = distance.cdist(inCoords, inCoords, 'euclidean') return distArray
def get_bounding_box(self): """Get the bounding box of this file.""" from pyproj import Geod geod = Geod(ellps='WGS84') dataset_group = DATASET_KEYS[self.datasets[0]] idx = 0 lons_ring = None lats_ring = None while True: path = 'Data_Products/{dataset_group}/{dataset_group}_Gran_{idx}/attr/' prefix = path.format(dataset_group=dataset_group, idx=idx) try: lats = self.file_content[prefix + 'G-Ring_Latitude'] lons = self.file_content[prefix + 'G-Ring_Longitude'] if lons_ring is None: lons_ring = lons lats_ring = lats else: prev_lon = lons_ring[0] prev_lat = lats_ring[0] dists = list(geod.inv(lon, lat, prev_lon, prev_lat)[2] for lon, lat in zip(lons, lats)) first_idx = np.argmin(dists) if first_idx == 2 and len(lons) == 8: lons_ring = np.hstack((lons[:3], lons_ring[:-2], lons[4:])) lats_ring = np.hstack((lats[:3], lats_ring[:-2], lats[4:])) else: raise NotImplementedError("Don't know how to handle G-Rings of length %d" % len(lons)) except KeyError: break idx += 1 return lons_ring, lats_ring
def midpoint_longest(north_lat, west_lon, south_lat, east_lon): g = Geod(ellps='WGS84') af, ab, dist = g.inv(west_lon, north_lat, east_lon, south_lat) rlon, rlat, az = g.fwd(west_lon, north_lat, af, dist/2) rlon += 180 if rlon < 0 else -180 rlon = round(rlon, 6) rlat = round(rlat, 6) return rlat, rlon
def addLengthMeters(self, stream_network): """ Adds length field in meters to network (The added field name will be 'LENGTH_M'). .. note:: This may be needed for generating the kfac file depending on the units of your raster. See: :doc:`gis_tools`. Parameters: stream_network(str): Path to stream network file. Here is an example of how to use this: .. code:: python import os from RAPIDpy.gis.taudem import TauDEM td = TauDEM() output_directory = '/path/to/output/files' td.addLengthMeters(os.path.join(output_directory,"stream_reach_file.shp")) """ network_shapefile = ogr.Open(stream_network, 1) network_layer = network_shapefile.GetLayer() network_layer_defn = network_layer.GetLayerDefn() #make sure projection EPSG:4326 network_layer_proj = network_layer.GetSpatialRef() geographic_proj = osr.SpatialReference() geographic_proj.ImportFromEPSG(4326) proj_transform = None if network_layer_proj != geographic_proj: proj_transform = osr.CoordinateTransformation(network_layer_proj, geographic_proj) #check for field create_field=True for i in xrange(network_layer_defn.GetFieldCount()): field_name = network_layer_defn.GetFieldDefn(i).GetName() if field_name == 'LENGTH_M': create_field=False break if create_field: network_layer.CreateField(ogr.FieldDefn('LENGTH_M', ogr.OFTReal)) geo_manager = Geod(ellps="WGS84") for network_feature in network_layer: feat_geom = network_feature.GetGeometryRef() #make sure coordinates are geographic if proj_transform: feat_geom.Transform(proj_transform) line = shapely_loads(feat_geom.ExportToWkb()) lon_list, lat_list = line.xy az1, az2, dist = geo_manager.inv(lon_list[:-1], lat_list[:-1], lon_list[1:], lat_list[1:]) network_feature.SetField('LENGTH_M', sum(dist)) network_layer.SetFeature(network_feature)
def getHorizontalDistance(self, point): """ Get horizontal distance (great circle distance, in km) between current point and provided point (point). """ g = Geod(ellps="sphere") forward_azimuth, back_azimuth, horizontal_distance = g.inv( self.longitude, self.latitude, point.longitude, point.latitude ) return horizontal_distance * 1e-3 # 1e-3 is needed to convert from m to km
def _distance(self, start, to): ''' Return distance. ''' q = Geod(ellps='WGS84') fa, ba, d =\ q.inv(start['lon'], start['lat'], to['lon'], to['lat']) return d
class Measurer: def __init__(self, ellps="clrk66"): self.geod = Geod( ellps=ellps ) def measure(self, shape): ret = 0 for pt1, pt2 in cons( shape.coords ): try: azm1, azm2, dist = self.geod.inv( pt1[0], pt1[1], pt2[0], pt2[1] ) except ValueError: continue ret += dist return ret
def cell_height(self): cell_height = np.full(self.shape, np.nan) geod = Geod(ellps='WGS84') for i in range(self.shape[0]): _az12, _az21, cell_length = geod.inv( self.longitude[i, 0], self.latitude[i, 0] + .25, self.longitude[i, 0], self.latitude[i, 0] - .25, ) cell_height[i, :] = cell_length return cell_height
def test_geod_nans(self): g = Geod(ellps='clrk66') (azi1, azi2, s12) = g.inv(43, 10, float('nan'), 20) self.assertTrue(azi1 != azi1) self.assertTrue(azi2 != azi2) self.assertTrue(s12 != s12) (azi1, azi2, s12) = g.inv(43, 10, 53, float('nan')) self.assertTrue(azi1 != azi1) self.assertTrue(azi2 != azi2) self.assertTrue(s12 != s12) # Illegal latitude is treated as NaN (azi1, azi2, s12) = g.inv(43, 10, 53, 91) self.assertTrue(azi1 != azi1) self.assertTrue(azi2 != azi2) self.assertTrue(s12 != s12) (lon2, lat2, azi2) = g.fwd(43, 10, float('nan'), 1e6) self.assertTrue(lon2 != lon2) self.assertTrue(lat2 != lat2) self.assertTrue(azi2 != azi2) (lon2, lat2, azi2) = g.fwd(43, 10, 20, float('nan')) self.assertTrue(lon2 != lon2) self.assertTrue(lat2 != lat2) self.assertTrue(azi2 != azi2) (lon2, lat2, azi2) = g.fwd(43, float('nan'), 20, 1e6) self.assertTrue(lon2 != lon2) self.assertTrue(lat2 != lat2) self.assertTrue(azi2 != azi2) # Illegal latitude is treated as NaN (lon2, lat2, azi2) = g.fwd(43, 91, 20, 1e6) self.assertTrue(lon2 != lon2) self.assertTrue(lat2 != lat2) self.assertTrue(azi2 != azi2) # Only lon2 is NaN (lon2, lat2, azi2) = g.fwd(float('nan'), 10, 20, 1e6) self.assertTrue(lon2 != lon2) self.assertTrue(lat2 == lat2) self.assertTrue(azi2 == azi2)
def size (self): from pyproj import Geod g = Geod(ellps='WGS84') lon_min = self.lonw lon_max = self.lone lat_min = self.lats lat_max = self.latn lon = (lon_min+lon_max)/2 lat = (lat_min+lat_max)/2 sn = g.inv (lon, lat_min, lon, lat_max, radians=False)[2] we = g.inv (lon_min, lat, lon_max, lat, radians=False)[2] return (sn, we)
def zero_padding(self, outfname, component, evlo, evla, dt, minV=1.5, iter0=None, iterf=None, diter=None, verbose=True): # - Some initialisations. ------------------------------------------------------------------ g = Geod(ellps='WGS84') dset = h5py.File(outfname) dset.attrs.create(name = 'theta_max', data=self.attrs["theta_max"], dtype='f') dset.attrs.create(name = 'theta_min', data=self.attrs["theta_min"], dtype='f') dset.attrs.create(name = 'phi_min', data=self.attrs["phi_min"], dtype='f') dset.attrs.create(name = 'phi_max', data=self.attrs["phi_max"], dtype='f') lat_min = 90.0 - self.attrs["theta_max"]*180.0/np.pi lat_max = 90.0 - self.attrs["theta_min"]*180.0/np.pi lon_min = self.attrs["phi_min"]*180.0/np.pi lon_max = self.attrs["phi_max"]*180.0/np.pi dset.attrs.create(name = 'lat_min', data=lat_min, dtype='f') dset.attrs.create(name = 'lat_max', data=lat_max, dtype='f') dset.attrs.create(name = 'lon_min', data=lon_min, dtype='f') dset.attrs.create(name = 'lon_max', data=lon_max, dtype='f') dset.attrs.create(name = 'depth', data=self.attrs['depth'], dtype='f') dset.attrs.create(name = 'n_procs', data=self.attrs['n_procs'], dtype='f') dset.attrs.create(name = 'rotation_axis', data=self.attrs['rotation_axis'], dtype='f') dset.attrs.create(name = 'rotation_angle', data=self.attrs['rotation_angle'], dtype='f') group = dset.create_group( name = component ) in_group= self[component] # - Loop over processor boxes and check if depth falls within the volume. ------------------ try: iterArr=np.arange(iter0 ,iterf+diter, diter, dtype=int) except: iterArr = in_group.keys() for iteration in iterArr: try: in_subgroup = in_group[str(iteration)] except KeyError: continue subgroup=group.create_group(name=str(iteration)) if verbose: print 'Zero padding snapshot for iteration =',iteration time = float(iteration) * dt; mindist = time * minV for iproc in in_subgroup.keys(): in_subdset = in_subgroup[iproc] field = in_subdset.value theta = in_subdset.attrs['theta'] phi = in_subdset.attrs['phi'] lat = 90.-theta/np.pi*180.; lon = phi/np.pi*180. lats, lons = np.meshgrid(lat, lon, indexing = 'ij') evlaArr = evla * np.ones(lats.shape); evloArr = evlo * np.ones(lats.shape) az, baz, distevent = g.inv(lons, lats, evloArr, evlaArr) distevent=distevent/1000. index_padding = distevent < mindist field[index_padding] = 0 subdset = subgroup.create_dataset(name=iproc, shape=field.shape, data=field) subdset.attrs.create(name = 'theta', data=theta, dtype='f') subdset.attrs.create(name = 'phi', data=phi, dtype='f') dset.close() return
def divide_line(pts, spacing=6.25, runin=0., ellps='WGS84', isegment0=0): """ Divide a line into equally spaced segments. Parameters ---------- pts : list of tuples List of point coordinates in longitude and latitude that define the line. Format is: ``[(lon_0, lat_0), (lon_1, lat_1), ..., (lon_n, lat_n)]``. spacing : float, optional Spacing between line segments in meters. runin : float, optional Length of a "run-in" segment prepended to the line. ellps : str, optional Name of the ellipse to use in geodetic calculations. Must be recognized by :class:`pyproj.Geod`. isegment0 : int, optional Sequence number of the first bin. Returns ------- bins : list List of (lon, lat, offset, sequence) tuples. """ gd = Geod(ellps=ellps) x = -runin _x = -runin ibin = isegment0 bins = [] for i in range(0, len(pts) - 1): _x0 = _x lon0, lat0 = pts[i] lon1, lat1 = pts[i + 1] faz, baz, dist = gd.inv(lon0, lat0, lon1, lat1) while _x <= dist: lon, lat, _ = gd.fwd(lon0, lat0, faz, _x) bins += [(lon, lat, x, ibin)] _x += spacing x += spacing ibin += 1 _x -= dist x -= _x if _x > 0: x += _x bins += [(lon1, lat1, x, ibin - 1)] return bins
def okada_synthetics(strike,dip,rake,length,width,lon_source,lat_source, depth_source,lon_obs,lat_obs,mu): ''' Calculate neu synthetics for a subfault using Okada analytical solutions ''' from okada_wrapper import dc3dwrapper from numpy import array,cos,sin,deg2rad,zeros from pyproj import Geod theta=strike-90 theta=deg2rad(theta) #Rotaion matrices since okada_wrapper is only for east striking fault R=array([[cos(theta),-sin(theta)],[sin(theta),cos(theta)]]) R2=array([[cos(-theta),-sin(-theta)],[sin(-theta),cos(-theta)]]) #position of point from lon/lat to x/y assuming subfault center is origin P=Geod(ellps='WGS84') az,baz,dist=P.inv(lon_source,lat_source,lon_obs,lat_obs) dist=dist/1000. x_obs=dist*sin(deg2rad(az)) y_obs=dist*cos(deg2rad(az)) #Calculate on rotated position xy=R.dot(array([x_obs, y_obs])) #Get Okada displacements lamb=mu alpha = (lamb + mu) / (lamb + 2 * mu) ss_in_m=1.0*cos(deg2rad(rake)) ds_in_m=1.0*sin(deg2rad(rake)) success, u, grad_u = dc3dwrapper(alpha, [xy[0], xy[1], 0.0],depth_source,dip, [-length/2., length/2.], [-width/2., width/2], [ss_in_m, ds_in_m, 0.0]) #Rotate output urot=R2.dot(array([[u[0]], [u[1]]])) u[0]=urot[0] u[1]=urot[1] #output n=u[1] e=u[0] z=u[2] return n,e,z
def midpoint_shortest(north_lat, west_lon, south_lat, east_lon): g = Geod(ellps='WGS84') af, ab, dist = g.inv(west_lon, north_lat, east_lon, south_lat) rlon, rlat, az = g.fwd(west_lon, north_lat, af, dist/2) # decimal places degrees distance # 0 1 111 km # 1 0.1 11.1 km # 2 0.01 1.11 km # 3 0.001 111 m # 4 0.0001 11.1 m # 5 0.00001 1.11 m # 6 0.000001 0.111 m # 7 0.0000001 1.11 cm # 8 0.00000001 1.11 mm rlon = round(rlon, 6) rlat = round(rlat, 6) return rlat, rlon
def getShortestDistance(self,point): """ Compute shortest distance (in km) between point and rupture. The shortest distance is defined as the minimum distance between the given point and the points constituting the rupture surface mesh. """ g = Geod(ellps="sphere") point_list = self.rupture_surface.ravel() lons_rup = numpy.array([point_list[i].longitude for i in range(len(point_list))]) lats_rup = numpy.array([point_list[i].latitude for i in range(len(point_list))]) lons_point = numpy.array([point.longitude for i in range(len(point_list))]) lats_point = numpy.array([point.latitude for i in range(len(point_list))]) fwd_azs,back_azs,hor_dists = g.inv(lons_point,lats_point,lons_rup,lats_rup) vert_dists = numpy.array([(point.depth - point_list[i].depth) * 1e3 for i in range(len(point_list))]) dists = numpy.sqrt(hor_dists**2 + vert_dists**2) return min(dists) * 1e-3
def __azdist(sacobj, ellps): """ Return forward/backazimuth and distance using pyproj (proj4 bindings) """ from pyproj import Geod g = Geod(ellps=ellps) stla, stlo = sacobj.stla, sacobj.stlo evla, evlo = sacobj.evla, sacobj.evlo az, baz, dist = g.inv(evlo, evla, stlo, stla) # convert units so that they show the same as SAC if az < 0: az += 360 if baz < 0: baz += 360 dist /= 1000 return az, baz, dist
def distances_from_cross_section(cross): """Calculate the distances in the x and y directions along a cross-section. Parameters ---------- cross : `xarray.DataArray` The input DataArray of a cross-section from which to obtain geometeric distances in the x and y directions. Returns ------- x, y : tuple of `xarray.DataArray` A tuple of the x and y distances as DataArrays """ if (CFConventionHandler.check_axis(cross.metpy.x, 'lon') and CFConventionHandler.check_axis(cross.metpy.y, 'lat')): # Use pyproj to obtain x and y distances from pyproj import Geod g = Geod(cross.metpy.cartopy_crs.proj4_init) lon = cross.metpy.x lat = cross.metpy.y forward_az, _, distance = g.inv(lon[0].values * np.ones_like(lon), lat[0].values * np.ones_like(lat), lon.values, lat.values) x = distance * np.sin(np.deg2rad(forward_az)) y = distance * np.cos(np.deg2rad(forward_az)) # Build into DataArrays x = xr.DataArray(x, coords=lon.coords, dims=lon.dims, attrs={'units': 'meters'}) y = xr.DataArray(y, coords=lat.coords, dims=lat.dims, attrs={'units': 'meters'}) elif (CFConventionHandler.check_axis(cross.metpy.x, 'x') and CFConventionHandler.check_axis(cross.metpy.y, 'y')): # Simply return what we have x = cross.metpy.x y = cross.metpy.y else: raise AttributeError('Sufficient horizontal coordinates not defined.') return x, y
def kml_trackers(request): trackers = Tracker.objects.filter(Q(view_users=request.user) | Q(creator=request.user)) placemarks = "" g = Geod(ellps='clrk66') added_tracker_pks = [] for tr in trackers: if tr.pk in added_tracker_pks: continue added_tracker_pks.append(tr.pk) pos_qs = Position.objects.filter(tracker=tr).order_by('-date') count = pos_qs.count() if not count: continue pos_qs = pos_qs.order_by('-date') pos = pos_qs[0] p = pos.point p_prev = None angle = 0.0 stay = None if datetime.datetime.now() - pos.date > datetime.timedelta(seconds=settings.MIN_LINK_TIMEOUT): stay = True elif pos.speed != None: stay = pos.speed <= settings.STAY_AVG_SPEED if count > 1: pos_prev = pos_qs[1] p_prev = pos_prev.point angle, angle2, dist = g.inv(p_prev.x, p_prev.y, p.x, p.y) if stay == None: avg_speed = dist/float((pos.date-pos_prev.date).seconds) avg_speed = avg_speed*10/36. logger.debug("avg_speed: %s" % avg_speed) stay = avg_speed <= settings.STAY_AVG_SPEED if stay == None: stay = True if stay: image_url = settings.MEDIA_URL + 'images/icons/busstop.png' graphic = 'circle' angle = 0.0 else: image_url = settings.MEDIA_URL + 'images/icons/bus.png' graphic = 'bus' marker_color = tr.marker_color if tr.marker_color else '00ff00' placemarks += """<Placemark><name>%s</name><description>%s</description><angle>%1.4f</angle><image>%s</image><graphic>%s</graphic><marker_color>#%s</marker_color><Point><coordinates>%1.6f,%1.6f</coordinates></Point></Placemark>""" % (tr.name, tr.description, angle, image_url, graphic, marker_color, p.x, p.y) kml = """<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.2"><Document>%s</Document></kml>""" % placemarks return HttpResponse(kml)