How Do You Animate A Dot Moving From Point To Point On A Map
At that place are a couple of approaches to this.
The matplotlib approach
I'll showtime with perchance the near basic if y'all are familiar with matplotlib, but this approach suffers from indirectly using cartopy's functionality, and is therefore harder to configure/extend.
There is a private _get_transformed_path
method on a Line2D object (the thing that is returned from plt.plot
). The resulting TransformedPath object has a get_transformed_path_and_affine
method, which basically will give united states the projected line (in the coordinate system of the Axes being fatigued).
In [i]: import cartopy.crs as ccrs In [three]: import matplotlib.pyplot as plt In [four]: ax = plt.axes(projection=ccrs.Robinson()) In [6]: ny_lon, ny_lat = -75, 43 In [seven]: delhi_lon, delhi_lat = 77.23, 28.61 In [eight]: [line] = plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat], ...: color='blue', linewidth=2, marking='o', ...: transform=ccrs.Geodetic(), ...: ) In [9]: t_path = line._get_transformed_path() In [10]: path_in_data_coords, _ = t_path.get_transformed_path_and_affine() In [xi]: path_in_data_coords.vertices Out[xi]: array([[-6425061.82215208, 4594257.92617961], [-5808923.84969279, 5250795.00604155], [-5206753.88613758, 5777772.51828996], [-4554622.94040482, 6244967.03723341], [-3887558.58343227, 6627927.97123701], [-3200922.19194864, 6932398.19937816], [-2480001.76507805, 7165675.95095855], [-1702269.5101901 , 7332885.72276795], [ -859899.12295981, 7431215.78426759], [ 23837.23431173, 7453455.61302756], [ 889905.10635756, 7397128.77301289], [ 1695586.66856764, 7268519.87627204], [ 2434052.81300274, 7073912.54130764], [ 3122221.22299409, 6812894.40443648], [ 3782033.80448001, 6478364.28561403], [ 4425266.18173684, 6062312.15662039], [ 5049148.25986903, 5563097.6328901 ], [ 5616318.74912886, 5008293.21452795], [ 6213232.98764984, 4307186.23400115], [ 6720608.93929235, 3584542.06839575], [ 7034261.06659143, 3059873.62740856]])
We tin can pull this together with matplotlib'southward animation functionality to exercise as requested:
import cartopy.crs as ccrs import matplotlib.animation as animation import matplotlib.pyplot every bit plt ax = plt.axes(projection=ccrs.Robinson()) ax.stock_img() ny_lon, ny_lat = -75, 43 delhi_lon, delhi_lat = 77.23, 28.61 [line] = plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat], color='blueish', linewidth=2, marker='o', transform=ccrs.Geodetic(), ) t_path = line._get_transformed_path() path_in_data_coords, _ = t_path.get_transformed_path_and_affine() # Depict the point that nosotros want to animate. [point] = plt.plot(ny_lon, ny_lat, marker='o', transform=ax.projection) def animate_point(i): verts = path_in_data_coords.vertices i = i % verts.shape[0] # Set the coordinates of the line to the coordinate of the path. point.set_data(verts[i, 0], verts[i, one]) ani = blitheness.FuncAnimation( ax.figure, animate_point, frames= path_in_data_coords.vertices.shape[0], interval=125, repeat=Truthful) ani.save('point_ani.gif', writer='imagemagick') plt.show()
The cartopy approach
Under the hood, cartopy's matplotlib implementation (as used above), is calling the project_geometry method. We may as well make use of this directly as it is often more than convenient to be using Shapely geometries than it is matplotlib Paths.
With this approach, we simply define a shapely geometry, and so construct the source and target coordinate reference systems that nosotros want to catechumen the geometry from/to:
target_cs.project_geometry(geometry, source_cs)
The just thing we have to lookout out for is that the event can be a MultiLineString (or more mostly, whatsoever Multi- geometry type). However, in our simple example, we don't need to bargain with that (incidentally, the same was true of the simple Path returned in the beginning example).
The code to produce a similar plot to above:
import cartopy.crs as ccrs import matplotlib.blitheness equally animation import matplotlib.pyplot as plt import numpy as np import shapely.geometry as sgeom ax = plt.axes(project=ccrs.Robinson()) ax.stock_img() ny_lon, ny_lat = -75, 43 delhi_lon, delhi_lat = 77.23, 28.61 line = sgeom.LineString([[ny_lon, ny_lat], [delhi_lon, delhi_lat]]) projected_line = ccrs.PlateCarree().project_geometry(line, ccrs.Geodetic()) # We only animate along one of the projected lines. if isinstance(projected_line, sgeom.MultiLineString): projected_line = projected_line.geoms[0] ax.add_geometries( [projected_line], ccrs.PlateCarree(), edgecolor='blueish', facecolor='none') [point] = plt.plot(ny_lon, ny_lat, marker='o', transform=ccrs.PlateCarree()) def animate_point(i): verts = np.array(projected_line.coords) i = i % verts.shape[0] # Set the coordinates of the line to the coordinate of the path. signal.set_data(verts[i, 0], verts[i, i]) ani = animation.FuncAnimation( ax.figure, animate_point, frames=len(projected_line.coords), interval=125, repeat=True) ani.salvage('projected_line_ani.gif', writer='imagemagick') plt.show()
Final remaaaaarrrrrrks....
The approach naturally generalises to animating whatsoever type of matplotlib Arrrrtist.... in this case, I took a flake more than control over the slap-up circle resolution, and I blithe an image along the great circle:
import cartopy.crs as ccrs import matplotlib.animation equally animation import matplotlib.pyplot as plt import numpy as np import shapely.geometry every bit sgeom ax = plt.axes(projection=ccrs.Mercator()) ax.stock_img() line = sgeom.LineString([[-5.9845, 37.3891], [-82.3666, 23.1136]]) # Higher resolution version of Mercator. Same workaround equally found in # https://github.com/SciTools/cartopy/problems/viii#issuecomment-326987465. class HighRes(ax.projection.__class__): @belongings def threshold(self): return super(HighRes, self).threshold / 100 projected_line = HighRes().project_geometry(line, ccrs.Geodetic()) # Nosotros only animate along one of the projected lines. if isinstance(projected_line, sgeom.MultiLineString): projected_line = projected_line.geoms[0] # Add the projected line to the map. ax.add_geometries( [projected_line], ax.projection, edgecolor='blueish', facecolor='none') def ll_to_extent(10, y, ax_size=(4000000, 4000000)): """ Render an image extent in centered on the given point with the given width and height. """ return [x - ax_size[0] / 2, x + ax_size[0] / ii, y - ax_size[1] / 2, y + ax_size[1] / 2] # Image from https://pixabay.com/en/sailing-ship-gunkhole-sail-pirate-28930/. pirate = plt.imread('pirates.png') img = ax.imshow(pirate, extent=ll_to_extent(0, 0), transform=ax.projection, origin='upper') ax.set_global() def animate_ship(i): verts = np.array(projected_line.coords) i = i % verts.shape[0] # Prepare the extent of the epitome to the coordinate of the path. img.set_extent(ll_to_extent(verts[i, 0], verts[i, i])) ani = animation.FuncAnimation( ax.figure, animate_ship, frames=len(projected_line.coords), interval=125, repeat=False) ani.save('arrrr.gif', writer='imagemagick') plt.prove()
All code and images for this answer can be found at https://gist.github.com/pelson/618a5f4ca003e56f06d43815b21848f6.
Source: https://stackoverflow.com/questions/51482082/animate-a-point-moving-along-path-between-two-points
Posted by: pettitsuded1943.blogspot.com
0 Response to "How Do You Animate A Dot Moving From Point To Point On A Map"
Post a Comment