Repository: fatiando/verde
Pull request #12 (2018-05-01 02:53:27)

Add function to make coordinates for a profile
Function `profile_coordinates` generates coordinates for a profile
between two points.


Patch:
diff --git a/verde/__init__.py b/verde/__init__.py
index ec9d0d5..56154fb 100644
--- a/verde/__init__.py
+++ b/verde/__init__.py
@@ -4,7 +4,7 @@ The Verde public API.
 from ._version import get_versions as _get_versions
 
 # Import functions/classes to make the API
-from .utils import scatter_points, grid_coordinates
+from .utils import scatter_points, grid_coordinates, profile_coordinates
 
 
 # Get the version number through versioneer
diff --git a/verde/utils.py b/verde/utils.py
index a29c0e9..2919c04 100644
--- a/verde/utils.py
+++ b/verde/utils.py
@@ -128,3 +128,63 @@ def grid_coordinates(region, shape):
     north_lines = np.linspace(s, n, nnorth)
     easting, northing = np.meshgrid(east_lines, north_lines)
     return easting, northing
+
+
+def profile_coordinates(point1, point2, size, coordinate_system='cartesian'):
+    """
+    Coordinates for a profile along a line between two points.
+
+    If on a geographic coordinate system, will calculate along a great circle.
+    Otherwise, will use a straight line.
+
+    Parameters
+    ----------
+    point1 : tuple or list
+        ``(easting, northing)`` West-East and South-North coordinates of the
+        first point, respectively.
+    point2 : tuple or list
+        ``(easting, northing)`` West-East and South-North coordinates of the
+        second point, respectively.
+    size : int
+        Number of points to sample along the line.
+    coordinate_system : str
+        The coordinate system used to define the points and the line. Either
+        ``'cartesian'`` or ``'geographic'``.
+
+    Returns
+    -------
+    easting, northing, distances : 1d arrays
+        The easting and northing coordinates of points along the straight line
+        and the distances from the first point.
+
+    Examples
+    --------
+
+    >>> east, north, dist = profile_coordinates((1, 10), (1, 20), size=11)
+    >>> print('easting:', ', '.join('{:.1f}'.format(i) for i in east))
+    easting: 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
+    >>> print('northing:', ', '.join('{:.1f}'.format(i) for i in north))
+    northing: 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0
+    >>> print('distance:', ', '.join('{:.1f}'.format(i) for i in dist))
+    distance: 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0
+
+    """
+    valid_coordinate_systems = ['cartesian', 'geographic']
+    if coordinate_system not in valid_coordinate_systems:
+        raise ValueError(
+            "Invalid coordinate system '{}'. Must be one of {}."
+            .format(coordinate_system, str(valid_coordinate_systems)))
+    if size <= 0:
+        raise ValueError("Invalid profile size '{}'. Must be > 0."
+                         .format(size))
+    if coordinate_system == 'geographic':
+        raise NotImplementedError()
+    elif coordinate_system == 'cartesian':
+        east1, north1 = point1
+        east2, north2 = point2
+        separation = np.sqrt((east1 - east2)**2 + (north1 - north2)**2)
+        distances = np.linspace(0, separation, size)
+        angle = np.arctan2(north2 - north1, east2 - east1)
+        easting = east1 + distances*np.cos(angle)
+        northing = north1 + distances*np.sin(angle)
+    return easting, northing, distances


Test patch:
diff --git a/verde/tests/test_utils.py b/verde/tests/test_utils.py
index 9d9ac7d..1abbdbb 100644
--- a/verde/tests/test_utils.py
+++ b/verde/tests/test_utils.py
@@ -4,6 +4,7 @@ Test the misc utilities in verde
 import pytest
 
 from ..utils import check_region
+from .. import profile_coordinates
 
 
 def test_check_region():
@@ -22,3 +23,16 @@ def test_check_region():
         check_region([-1, -2, -4, -3])
     with pytest.raises(ValueError):
         check_region([-2, -1, -2, -3])
+
+
+def test_profile_coordiantes_fails():
+    "Should raise an exception for invalid input"
+    with pytest.raises(ValueError):
+        profile_coordinates((0, 1), (1, 2), size=0)
+    with pytest.raises(ValueError):
+        profile_coordinates((0, 1), (1, 2), size=-10)
+    with pytest.raises(ValueError):
+        profile_coordinates((0, 1), (1, 2), size=10, coordinate_system="meh")
+    with pytest.raises(NotImplementedError):
+        profile_coordinates((0, 1), (1, 2), size=10,
+                            coordinate_system="geographic")