Repository: lace/vg

Issue:
Clarify what goes in `vg` vs `polliwog`
Since there is a closely related library, [polliwog](https://github.com/lace/polliwog) which does a lot of computational geometry, it's useful to clarify what belongs here vs. there.

Accordingly, the idea is to clarify this library's purpose:

> A vector-geometry toolbelt for dealing with 3D points and vectors

and say that anything more complicated is general computational geometry, and goes in polliwog.

In particular, transformation matrices will be scoped to polliwog.

Accordingly, the matrix functions will be removed in the next major release.

Refs:

- lace/polliwog#107
- lace/polliwog#113

Discussion:

Patch:
diff --git a/README.md b/README.md
index ecfc146..37a6e9c 100644
--- a/README.md
+++ b/README.md
@@ -9,9 +9,9 @@ vg
 [![docs build](https://img.shields.io/readthedocs/vgpy.svg?style=flat-square)][docs build]
 [![code style](https://img.shields.io/badge/code%20style-black-black.svg?style=flat-square)][black]
 
-A **v**ery **g**ood vector-geometry and linear-algebra toolbelt. Linear
-algebra for humans. Simple [NumPy][] operations made readable, built to
-scale from prototyping to production.
+A **v**ery **g**ood vector-geometry toolbelt for dealing with 3D points and
+vectors. These are simple [NumPy][] operations made readable, built to scale
+from prototyping to production.
 
 See the complete API reference: https://vgpy.readthedocs.io/en/latest/
 
diff --git a/doc/index.md b/doc/index.md
index 3ac896c..94503b2 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -1,7 +1,8 @@
 vg
 ==
 
-**vg** is a **v**ery **g**ood vector-geometry and linear-algebra toolbelt.
+**vg** is a **v**ery **g**ood vector-geometry toolbelt for dealing with 3D
+points and vectors.
 
 Motivation
 ----------
@@ -117,3 +118,28 @@ Versioning
 This library adheres to [Semantic Versioning][semver].
 
 [semver]: https://semver.org/
+
+
+If you like vg you might also like &hellip;
+-------------------------------------------
+
+### [polliwog][]
+
+Polliwog is a 2D and 3D computational geometry library. Like vg, it's designed
+to scale from prototyping to production. It includes vectorized geometric
+operations, transforms, and primitives like planes, polygonal chains, and
+axis-aligned bounding boxes. Implemented in pure Python/NumPy. It is depends on
+vg and is lightweight and fast.
+
+*Note:* vg is limited in scope to dealing with 3D points and vectors. Almost
+anything more complicated is considered general computational geometry, and goes
+in polliwog instead.
+
+### [ounce][]
+
+Fast, simple, non-fancy, and non-magical package for manipulating units of
+measure. A faster and less fancy counterpart to [Pint][].
+
+[polliwog]: https://polliwog.readthedocs.io/en/latest/
+[ounce]: https://ounce.readthedocs.io/en/latest/
+[pint]: https://pint.readthedocs.io/en/stable/
diff --git a/setup.py b/setup.py
index f48be6f..d606b3b 100755
--- a/setup.py
+++ b/setup.py
@@ -13,7 +13,7 @@ install_requires = ["numpy"]
 setup(
     name="vg",
     version=version_info["__version__"],
-    description="Linear algebra for humans: a very good vector-geometry and linear-algebra toolbelt",
+    description="A vector-geometry toolbelt for dealing with 3D points and vectors",
     long_description=readme,
     long_description_content_type="text/markdown",
     author="Metabolize, Body Labs, and other contributors",
diff --git a/vg/matrix.py b/vg/matrix.py
index 4356fc0..d26ab96 100644
--- a/vg/matrix.py
+++ b/vg/matrix.py
@@ -4,6 +4,9 @@ from ._helpers import raise_dimension_error
 
 def pad_with_ones(matrix):
     """
+    Deprecated. Matrix functions have been moved to polliwog. Will be removed in
+    vg 2.
+
     Add a column of ones. Transform from:
         array([[1., 2., 3.],
                [2., 3., 4.],
@@ -12,8 +15,15 @@ def pad_with_ones(matrix):
         array([[1., 2., 3., 1.],
                [2., 3., 4., 1.],
                [5., 6., 7., 1.]])
-
     """
+    import warnings
+
+    warnings.warn(
+        "`vg.matrix.pad_with_ones()` has been deprecated and will be removed in vg 2. "
+        + "Matrix functions have been moved to polliwog.",
+        DeprecationWarning,
+    )
+
     if matrix.ndim != 2 or matrix.shape[1] != 3:
         raise ValueError("Invalid shape %s: pad expects nx3" % (matrix.shape,))
     return np.pad(matrix, ((0, 0), (0, 1)), mode="constant", constant_values=1)
@@ -21,6 +31,9 @@ def pad_with_ones(matrix):
 
 def unpad(matrix):
     """
+    Deprecated. Matrix functions have been moved to polliwog. Will be removed in
+    vg 2.
+
     Strip off a column (e.g. of ones). Transform from:
         array([[1., 2., 3., 1.],
                [2., 3., 4., 1.],
@@ -29,8 +42,15 @@ def unpad(matrix):
         array([[1., 2., 3.],
                [2., 3., 4.],
                [5., 6., 7.]])
-
     """
+    import warnings
+
+    warnings.warn(
+        "`vg.matrix.unpad()` has been deprecated and will be removed in vg 2. "
+        + "Matrix functions have been moved to polliwog.",
+        DeprecationWarning,
+    )
+
     if matrix.ndim != 2 or matrix.shape[1] != 4:
         raise ValueError("Invalid shape %s: unpad expects nx4" % (matrix.shape,))
     if not all(matrix[:, 3] == 1.0):
@@ -40,9 +60,20 @@ def unpad(matrix):
 
 def transform(vertices, transform):
     """
+    Deprecated. Will be removed in vg 2. Use
+    `polliwog.transform.apply_transform()` instead.
+
     Apply the given transformation matrix to the vertices using homogenous
     coordinates.
     """
+    import warnings
+
+    warnings.warn(
+        "`vg.matrix.transform()` has been deprecated and will be removed in vg 2. "
+        + "Use `polliwog.transform.apply_transform()` instead.",
+        DeprecationWarning,
+    )
+
     if transform.shape != (4, 4):
         raise ValueError("Transformation matrix should be 4x4")
 


Test patch:
diff --git a/vg/test_aligned_with.py b/vg/test_aligned_with.py
index cd4f0ed..3445478 100644
--- a/vg/test_aligned_with.py
+++ b/vg/test_aligned_with.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_aligned_with():
diff --git a/vg/test_almost_collinear.py b/vg/test_almost_collinear.py
index 5de9e4b..3a27672 100644
--- a/vg/test_almost_collinear.py
+++ b/vg/test_almost_collinear.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_almost_collinear():
diff --git a/vg/test_almost_equal.py b/vg/test_almost_equal.py
index 398a38e..5399e39 100644
--- a/vg/test_almost_equal.py
+++ b/vg/test_almost_equal.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_almost_equal():
diff --git a/vg/test_almost_unit_length.py b/vg/test_almost_unit_length.py
index e772d4b..7cbb483 100644
--- a/vg/test_almost_unit_length.py
+++ b/vg/test_almost_unit_length.py
@@ -1,6 +1,6 @@
 import math
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_almost_unit_length():
diff --git a/vg/test_almost_zero.py b/vg/test_almost_zero.py
index de8cc0d..b77de9e 100644
--- a/vg/test_almost_zero.py
+++ b/vg/test_almost_zero.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_almost_zero():
diff --git a/vg/test_angle.py b/vg/test_angle.py
index 4b0849c..80a9663 100644
--- a/vg/test_angle.py
+++ b/vg/test_angle.py
@@ -1,7 +1,7 @@
 import math
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_basic():
diff --git a/vg/test_apex.py b/vg/test_apex.py
index c2e6e3b..ccc23a8 100644
--- a/vg/test_apex.py
+++ b/vg/test_apex.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_apex_functions():
diff --git a/vg/test_average.py b/vg/test_average.py
index 7c95801..0853dce 100644
--- a/vg/test_average.py
+++ b/vg/test_average.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_average():
diff --git a/vg/test_basis.py b/vg/test_basis.py
index 925c7cb..f58a306 100644
--- a/vg/test_basis.py
+++ b/vg/test_basis.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_constants():
diff --git a/vg/test_cross.py b/vg/test_cross.py
index 0b9cd0e..c7f279d 100644
--- a/vg/test_cross.py
+++ b/vg/test_cross.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_cross():
diff --git a/vg/test_dot.py b/vg/test_dot.py
index 330ce6e..eeccc81 100644
--- a/vg/test_dot.py
+++ b/vg/test_dot.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_dot():
diff --git a/vg/test_euclidean_distance.py b/vg/test_euclidean_distance.py
index 353a811..7c1253c 100644
--- a/vg/test_euclidean_distance.py
+++ b/vg/test_euclidean_distance.py
@@ -1,6 +1,6 @@
 import math
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_euclidean_distance():
diff --git a/vg/test_farthest.py b/vg/test_farthest.py
index 6af5f4f..a4f1a20 100644
--- a/vg/test_farthest.py
+++ b/vg/test_farthest.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_farthest():
diff --git a/vg/test_magnitude.py b/vg/test_magnitude.py
index 7dcf438..63c733b 100644
--- a/vg/test_magnitude.py
+++ b/vg/test_magnitude.py
@@ -1,7 +1,7 @@
 import math
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_magnitude():
diff --git a/vg/test_matrix_pad_with_ones.py b/vg/test_matrix_pad_with_ones.py
index 3a5b56c..8d7fe0c 100644
--- a/vg/test_matrix_pad_with_ones.py
+++ b/vg/test_matrix_pad_with_ones.py
@@ -1,25 +1,38 @@
 import numpy as np
 import pytest
-from .matrix import pad_with_ones
+from vg.matrix import pad_with_ones
 
 
 def test_pad_with_ones():
-    np.testing.assert_array_equal(
-        pad_with_ones(np.array([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0], [5.0, 6.0, 7.0]])),
-        np.array([[1.0, 2.0, 3.0, 1.0], [2.0, 3.0, 4.0, 1.0], [5.0, 6.0, 7.0, 1.0]]),
-    )
+    with pytest.deprecated_call():
+        np.testing.assert_array_equal(
+            pad_with_ones(
+                np.array([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0], [5.0, 6.0, 7.0]])
+            ),
+            np.array(
+                [[1.0, 2.0, 3.0, 1.0], [2.0, 3.0, 4.0, 1.0], [5.0, 6.0, 7.0, 1.0]]
+            ),
+        )
 
 
 def test_pad_with_wrong_dimensions():
     # NB: on windows, the sizes here will render as 3L, not 3:
-    with pytest.raises(
-        ValueError, match=r"^Invalid shape \(3L?, 4L?\): pad expects nx3$"
-    ):
-        pad_with_ones(
-            np.array(
-                [[1.0, 2.0, 3.0, 42.0], [2.0, 3.0, 4.0, 42.0], [5.0, 6.0, 7.0, 42.0]]
+    with pytest.deprecated_call():
+        with pytest.raises(
+            ValueError, match=r"^Invalid shape \(3L?, 4L?\): pad expects nx3$"
+        ):
+            pad_with_ones(
+                np.array(
+                    [
+                        [1.0, 2.0, 3.0, 42.0],
+                        [2.0, 3.0, 4.0, 42.0],
+                        [5.0, 6.0, 7.0, 42.0],
+                    ]
+                )
             )
-        )
 
-    with pytest.raises(ValueError, match=r"^Invalid shape \(3L?,\): pad expects nx3$"):
-        pad_with_ones(np.array([1.0, 2.0, 3.0]))
+    with pytest.deprecated_call():
+        with pytest.raises(
+            ValueError, match=r"^Invalid shape \(3L?,\): pad expects nx3$"
+        ):
+            pad_with_ones(np.array([1.0, 2.0, 3.0]))
diff --git a/vg/test_matrix_transform.py b/vg/test_matrix_transform.py
index 9ead30e..89637b5 100644
--- a/vg/test_matrix_transform.py
+++ b/vg/test_matrix_transform.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from .matrix import transform as apply_transform
+from vg.matrix import transform as apply_transform
 
 scale_factor = np.array([3.0, 0.5, 2.0])
 transform = np.array(
@@ -16,19 +16,26 @@ transform = np.array(
 def test_apply_homogeneous():
     point = np.array([5.0, 0.0, 1.0])
     expected_point = np.array([15.0, 0.0, 2.0])
-    np.testing.assert_array_equal(apply_transform(point, transform), expected_point)
+    with pytest.deprecated_call():
+        np.testing.assert_array_equal(apply_transform(point, transform), expected_point)
 
 
 def test_apply_homogeneous_stacked():
     points = np.array([[1.0, 2.0, 3.0], [5.0, 0.0, 1.0]])
     expected_points = np.array([[3.0, 1.0, 6.0], [15.0, 0.0, 2.0]])
-    np.testing.assert_array_equal(apply_transform(points, transform), expected_points)
+    with pytest.deprecated_call():
+        np.testing.assert_array_equal(
+            apply_transform(points, transform), expected_points
+        )
 
 
 def test_apply_homogeneous_error():
-    with pytest.raises(ValueError, match="Transformation matrix should be 4x4"):
-        apply_transform(np.array([1.0, 2.0, 3.0]), np.array([1.0]))
-    with pytest.raises(ValueError, match=r"Vertices should be \(3,\) or Nx3"):
-        apply_transform(np.array([1.0, 2.0]), transform)
-    with pytest.raises(ValueError, match="Not sure what to do with 3 dimensions"):
-        apply_transform(np.array([[[1.0, 2.0, 3.0]]]), transform)
+    with pytest.deprecated_call():
+        with pytest.raises(ValueError, match="Transformation matrix should be 4x4"):
+            apply_transform(np.array([1.0, 2.0, 3.0]), np.array([1.0]))
+    with pytest.deprecated_call():
+        with pytest.raises(ValueError, match=r"Vertices should be \(3,\) or Nx3"):
+            apply_transform(np.array([1.0, 2.0]), transform)
+    with pytest.deprecated_call():
+        with pytest.raises(ValueError, match="Not sure what to do with 3 dimensions"):
+            apply_transform(np.array([[[1.0, 2.0, 3.0]]]), transform)
diff --git a/vg/test_matrix_unpad.py b/vg/test_matrix_unpad.py
index 68ebe41..004f764 100644
--- a/vg/test_matrix_unpad.py
+++ b/vg/test_matrix_unpad.py
@@ -1,28 +1,36 @@
 import numpy as np
 import pytest
-from .matrix import unpad
+from vg.matrix import unpad
 
 
 def test_unpad():
-    np.testing.assert_array_equal(
-        unpad(
-            np.array([[1.0, 2.0, 3.0, 1.0], [2.0, 3.0, 4.0, 1.0], [5.0, 6.0, 7.0, 1.0]])
-        ),
-        np.array([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0], [5.0, 6.0, 7.0]]),
-    )
+    with pytest.deprecated_call():
+        np.testing.assert_array_equal(
+            unpad(
+                np.array(
+                    [[1.0, 2.0, 3.0, 1.0], [2.0, 3.0, 4.0, 1.0], [5.0, 6.0, 7.0, 1.0]]
+                )
+            ),
+            np.array([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0], [5.0, 6.0, 7.0]]),
+        )
 
     # NB: on windows, the sizes here will render as 3L, not 3:
-    with pytest.raises(
-        ValueError, match=r"^Invalid shape \(3L?, 3L?\): unpad expects nx4$"
-    ):
-        unpad(np.array([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0], [5.0, 6.0, 7.0]]))
+    with pytest.deprecated_call():
+        with pytest.raises(
+            ValueError, match=r"^Invalid shape \(3L?, 3L?\): unpad expects nx4$"
+        ):
+            unpad(np.array([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0], [5.0, 6.0, 7.0]]))
 
-    with pytest.raises(
-        ValueError, match=r"^Invalid shape \(4L?,\): unpad expects nx4$"
-    ):
-        unpad(np.array([1.0, 2.0, 3.0, 4.0]))
+    with pytest.deprecated_call():
+        with pytest.raises(
+            ValueError, match=r"^Invalid shape \(4L?,\): unpad expects nx4$"
+        ):
+            unpad(np.array([1.0, 2.0, 3.0, 4.0]))
 
-    with pytest.raises(ValueError, match="Expected a column of ones"):
-        unpad(
-            np.array([[1.0, 2.0, 3.0, 1.0], [2.0, 3.0, 4.0, 1.0], [5.0, 6.0, 7.0, 3.0]])
-        )
+    with pytest.deprecated_call():
+        with pytest.raises(ValueError, match="Expected a column of ones"):
+            unpad(
+                np.array(
+                    [[1.0, 2.0, 3.0, 1.0], [2.0, 3.0, 4.0, 1.0], [5.0, 6.0, 7.0, 3.0]]
+                )
+            )
diff --git a/vg/test_nearest.py b/vg/test_nearest.py
index 0c9e966..fb53a69 100644
--- a/vg/test_nearest.py
+++ b/vg/test_nearest.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_nearest():
diff --git a/vg/test_normalize.py b/vg/test_normalize.py
index 626c9c0..6621fca 100644
--- a/vg/test_normalize.py
+++ b/vg/test_normalize.py
@@ -1,7 +1,7 @@
 import math
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_normalize():
diff --git a/vg/test_pca.py b/vg/test_pca.py
index d97346a..b92b8ac 100644
--- a/vg/test_pca.py
+++ b/vg/test_pca.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_principal_components():
diff --git a/vg/test_perpendicular.py b/vg/test_perpendicular.py
index a8a41bb..095d578 100644
--- a/vg/test_perpendicular.py
+++ b/vg/test_perpendicular.py
@@ -1,7 +1,7 @@
 import math
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_perpendicular():
diff --git a/vg/test_project.py b/vg/test_project.py
index 2552cd9..cca20e3 100644
--- a/vg/test_project.py
+++ b/vg/test_project.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_project():
diff --git a/vg/test_reject.py b/vg/test_reject.py
index 48cb175..052e234 100644
--- a/vg/test_reject.py
+++ b/vg/test_reject.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_reject():
diff --git a/vg/test_reject_axis.py b/vg/test_reject_axis.py
index e90f4e8..60dfcc7 100644
--- a/vg/test_reject_axis.py
+++ b/vg/test_reject_axis.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_reject_axis():
diff --git a/vg/test_rotate.py b/vg/test_rotate.py
index 055c33d..4d66169 100644
--- a/vg/test_rotate.py
+++ b/vg/test_rotate.py
@@ -1,7 +1,7 @@
 import math
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 around_axis = np.array([0.0, 2.0, -1.0])
diff --git a/vg/test_scale_factor.py b/vg/test_scale_factor.py
index 78c9419..6c4e438 100644
--- a/vg/test_scale_factor.py
+++ b/vg/test_scale_factor.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_scale_factor():
diff --git a/vg/test_shape.py b/vg/test_shape.py
index 412549c..0b09948 100644
--- a/vg/test_shape.py
+++ b/vg/test_shape.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from .shape import check, check_value, check_value_any, columnize
+from vg.shape import check, check_value, check_value_any, columnize
 
 
 def test_check_value_valid():
diff --git a/vg/test_signed_angle.py b/vg/test_signed_angle.py
index d464120..b43d077 100644
--- a/vg/test_signed_angle.py
+++ b/vg/test_signed_angle.py
@@ -1,5 +1,5 @@
 import numpy as np
-from . import core as vg
+import vg
 
 
 def test_basic():
diff --git a/vg/test_within.py b/vg/test_within.py
index e84ee3b..cd92dd0 100644
--- a/vg/test_within.py
+++ b/vg/test_within.py
@@ -1,6 +1,6 @@
 import numpy as np
 import pytest
-from . import core as vg
+import vg
 
 
 def test_within():