-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refine plate polygons / lines below a predefined threshold for plotting #145
Comments
The approach that was used to densify line segments/polygons (i.e. using I needed to solve the same problem when I needed to render shapefiles from GPlates in ParaView, and at first I also tried to use
Below is the function I wrote in Python which performs steps 2 to 5 on a single pair of coordinates. It should be fairly easy to speed up by performing the calculations on shape (n,3) import numpy as np
def densify_great_circle(array1: np.ndarray, array2: np.ndarray, max_angle: float=np.pi/180):
'''
Given two arrays of shape (3,) of points on the surface of a unit sphere, return a sequence of points along the great circle between them, with a separating angle of no more than `max_angle`.
'''
# get the angle between the two points
angle = np.linalg.norm(np.cross(array1, array2))
# exit if the angle between the points is already smaller than the maximum allowed angle
if angle < max_angle:
return
# get the number of needed in-between vectors
n = int(np.floor(angle / max_angle))
# get the angle for the in-between vectors
sub_angle = angle / (n + 1)
# get basis vectors for plane on which the two vectors lie
basis0 = array1 / np.linalg.norm(array1)
basis2 = np.cross(array1, array2) / np.linalg.norm(np.cross(array1, array2))
basis1 = np.cross(basis2, basis0)
sub_vectors = []
# create the in-between vectors
for i in range(n):
sub_vector = basis0 * np.cos((i + 1) * sub_angle) + basis1 * np.sin((i + 1) * sub_angle)
sub_vector = sub_vector
sub_vectors.append(sub_vector)
return sub_vectors |
There's also pygplates.GreatCircleArc.to_tessellated() that I think should reproduce the above algorithm (ie, return uniformly spaced points along a great circle arc defined by two points). And there's a version for polylines and polygons that repeats that process for each segment/arc of a polyline or polygon, but returns a tessellated polyline or polygon instead of a list of points (but that can be converted to a list of lat/lon points using polygeom.to_lat_lon_array())). Note that there can be non-uniform tessellation across great circle arcs - in the docs "The distance between adjacent points (in the tessellated polyline) will not be exactly uniform. This is because each segment in the original polyline is tessellated to the nearest integer number of points (that keeps that segment under the threshold) and hence each original segment will have a slightly different tessellation angle.". By it may be easier to use your function. Especially if you want to change the details of the tessellation later - eg, uniform tessellation across an entire polyline or polygon - where you might specify an exact spacing angle (with no integer truncation) that leads to the points all being equidistant across the entire polyline/polygon (except for the last point). That's an option I will eventually add to pyGPlates. |
The default tessellation is now set to 1 degree: Line 707 in bd3e4b8
These are not great circle distances, as far as I can see. The relevant code is in |
Some plotting artefacts occur when there are very few points that define a polygon or line. For example, mid-ocean ridge geometries in the plot below have very few points and do not plot correctly.
Maybe there is some way to do this in cartopy but I think we may need to densify these segments so that they follow (or closely approximate) the expected great circle geometry.
The text was updated successfully, but these errors were encountered: