Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions src/compas/data/encoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from .exceptions import DecoderError

IDictionary = None
numpy_support = False
numpy_support = None # type: bool | None
dotnet_support = False

# We don't do this from `compas.IPY` to avoid circular imports
Expand All @@ -27,18 +27,15 @@
except: # noqa: E722
pass

try:
import numpy as np

try:
np_float = np.float_
except AttributeError:
np_float = np.float64

numpy_support = True
except (ImportError, SyntaxError):
numpy_support = False

def _is_numpy_available(): # type (...) -> bool
global numpy_support
if numpy_support is None:
try:
import numpy.version # noqa: F401
numpy_support = True
except (ImportError, SyntaxError):
numpy_support = False
return numpy_support

def cls_from_dtype(dtype, inheritance=None): # type: (...) -> Type[Data]
"""Get the class object corresponding to a COMPAS data type specification.
Expand Down Expand Up @@ -144,7 +141,8 @@ def default(self, o):
if hasattr(o, "__next__"):
return list(o)

if numpy_support:
if _is_numpy_available():
import numpy as np
if isinstance(o, np.ndarray):
return o.tolist()
if isinstance(
Expand All @@ -164,7 +162,9 @@ def default(self, o):
), # type: ignore
):
return int(o)
if isinstance(o, (np_float, np.float16, np.float32, np.float64)): # type: ignore
if hasattr(np, "float_") and isinstance(o, np.float_): # type: ignore
return float(o)
if isinstance(o, (np.float16, np.float32, np.float64)): # type: ignore
return float(o)
if isinstance(o, np.bool_):
return bool(o)
Expand Down
28 changes: 21 additions & 7 deletions src/compas/geometry/_core/transformations_numpy.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
from numpy import asarray
from numpy import hstack
from numpy import ones
from numpy import tile
from numpy import vectorize
from scipy.linalg import solve # type: ignore

from ._algebra import cross_vectors


Expand All @@ -31,6 +24,8 @@ def transform_points_numpy(points, T):
>>> points_transformed = transform_points_numpy(points, T)

"""
from numpy import asarray

T = asarray(T)
points = homogenize_numpy(points, w=1.0)
return dehomogenize_numpy(points.dot(T.T))
Expand Down Expand Up @@ -59,6 +54,8 @@ def transform_vectors_numpy(vectors, T):
>>> vectors_transformed = transform_vectors_numpy(vectors, T)

"""
from numpy import asarray

T = asarray(T)
vectors = homogenize_numpy(vectors, w=0.0)
return dehomogenize_numpy(vectors.dot(T.T))
Expand Down Expand Up @@ -87,6 +84,8 @@ def transform_frames_numpy(frames, T):
>>> transformed_frames = transform_frames_numpy(frames, T)

"""
from numpy import asarray

T = asarray(T)
points_and_vectors = homogenize_and_flatten_frames_numpy(frames)
return dehomogenize_and_unflatten_frames_numpy(points_and_vectors.dot(T.T))
Expand Down Expand Up @@ -117,6 +116,9 @@ def world_to_local_coordinates_numpy(frame, xyz):
True

"""
from numpy import asarray
from scipy.linalg import solve # type: ignore

origin = frame[0]
uvw = [frame[1], frame[2], cross_vectors(frame[1], frame[2])]
uvw = asarray(uvw).T
Expand Down Expand Up @@ -154,6 +156,8 @@ def local_to_world_coordinates_numpy(frame, rst):
True

"""
from numpy import asarray

origin = frame[0]
uvw = [frame[1], frame[2], cross_vectors(frame[1], frame[2])]

Expand Down Expand Up @@ -191,6 +195,10 @@ def homogenize_numpy(data, w=1.0):
True

"""
from numpy import asarray
from numpy import hstack
from numpy import ones

data = asarray(data)
data = hstack((data, w * ones((data.shape[0], 1))))
return data
Expand All @@ -216,6 +224,8 @@ def dehomogenize_numpy(data):
True

"""
from numpy import asarray
from numpy import vectorize

def func(a):
return a if a else 1.0
Expand Down Expand Up @@ -248,6 +258,10 @@ def homogenize_and_flatten_frames_numpy(frames):
True

"""
from numpy import asarray
from numpy import hstack
from numpy import tile

n = len(frames)
frames = asarray(frames).reshape(n * 3, 3)
extend = tile(asarray([1, 0, 0]).reshape(3, 1), (n, 1))
Expand Down
29 changes: 17 additions & 12 deletions src/compas/geometry/bbox_numpy.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
from numpy import amax
from numpy import amin
from numpy import argmax
from numpy import argmin
from numpy import array
from numpy import asarray
from numpy import dot
from numpy import sum
from numpy import vstack
from numpy import zeros
from scipy.spatial import ConvexHull

from compas.geometry import length_vector
from compas.geometry import local_axes
from compas.geometry import local_to_world_coordinates_numpy
Expand Down Expand Up @@ -78,6 +66,9 @@ def oriented_bounding_box_numpy(points, tol=None):
True

"""
from numpy import asarray
from numpy import vstack

points = asarray(points)
n, dim = points.shape

Expand Down Expand Up @@ -156,6 +147,9 @@ def oriented_bounding_box_xy_numpy(points):
:func:`compas.geometry.oriented_bounding_box_numpy`

"""
from numpy import asarray
from numpy import zeros

points = asarray(points)
n, dim = points.shape

Expand Down Expand Up @@ -192,6 +186,10 @@ def minimum_volume_box(points, return_size=False):
XYZ coordinates of 8 points defining a box.

"""
from numpy import amax
from numpy import amin
from scipy.spatial import ConvexHull

hull = ConvexHull(points)
xyz = points[hull.vertices]
boxes = []
Expand Down Expand Up @@ -248,6 +246,13 @@ def minimum_area_rectangle_xy(points, return_size=False):
XYZ coordinates of 4 points defining a rectangle.

"""
from numpy import argmax
from numpy import argmin
from numpy import array
from numpy import dot
from numpy import sum
from scipy.spatial import ConvexHull

boxes = []

points = points[:, :2]
Expand Down
13 changes: 7 additions & 6 deletions src/compas/geometry/bestfit_numpy.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
from numpy import asarray
from numpy import sqrt
from numpy import zeros
from numpy.linalg import lstsq
from scipy.optimize import leastsq

from compas.geometry import local_to_world_coordinates_numpy
from compas.geometry import pca_numpy
from compas.geometry import world_to_local_coordinates_numpy
Expand Down Expand Up @@ -155,6 +149,9 @@ def bestfit_circle_numpy(points):
Available at: http://scipy-cookbook.readthedocs.io/items/Least_Squares_Circle.html.

"""
from numpy import sqrt
from scipy.optimize import leastsq

o, uvw, _ = pca_numpy(points)
frame = [o, uvw[0], uvw[1]]

Expand Down Expand Up @@ -237,6 +234,10 @@ def bestfit_sphere_numpy(points):
Available at: https://jekel.me/2015/Least-Squares-Sphere-Fit/.

"""
from numpy import asarray
from numpy import sqrt
from numpy import zeros
from numpy.linalg import lstsq

# Assemble the A matrix
spX = asarray([p[0] for p in points])
Expand Down
10 changes: 6 additions & 4 deletions src/compas/geometry/hull_numpy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
from numpy import asarray
from scipy.spatial import ConvexHull


def convex_hull_numpy(points):
"""Compute the convex hull of a set of points.

Expand Down Expand Up @@ -34,6 +30,9 @@ def convex_hull_numpy(points):
with :func:`compas.topology.unify_cycles`.

"""
from numpy import asarray
from scipy.spatial import ConvexHull

points = asarray(points)
n, dim = points.shape

Expand Down Expand Up @@ -71,6 +70,9 @@ def convex_hull_xy_numpy(points):
convex_hull_numpy

"""
from numpy import asarray
from scipy.spatial import ConvexHull

points = asarray(points)
n, dim = points.shape

Expand Down
19 changes: 10 additions & 9 deletions src/compas/geometry/icp_numpy.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import numpy as np
from numpy import argmin
from numpy import asarray
from numpy.linalg import det
from numpy.linalg import multi_dot
from scipy.linalg import norm
from scipy.linalg import svd
from scipy.spatial.distance import cdist

from compas.geometry import pca_numpy
from compas.geometry import transform_points_numpy
from compas.linalg import normrow
from compas.tolerance import TOL


def bestfit_transform(A, B):
import numpy as np
from numpy.linalg import det
from scipy.linalg import svd

n, m = A.shape
Am = np.mean(A, axis=0)
Bm = np.mean(B, axis=0)
Expand Down Expand Up @@ -76,6 +71,12 @@ def icp_numpy(source, target, tol=None, maxiter=100):
The algorithm terminates when the alignment error is below a specified tolerance.

"""
from numpy import argmin
from numpy import asarray
from numpy.linalg import multi_dot
from scipy.linalg import norm
from scipy.spatial.distance import cdist

from compas.geometry import Frame
from compas.geometry import Transformation

Expand Down
7 changes: 3 additions & 4 deletions src/compas/geometry/pca_numpy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
from numpy import asarray
from scipy.linalg import svd # type: ignore


def pca_numpy(data):
"""Compute the principle components of a set of data points.

Expand Down Expand Up @@ -37,6 +33,9 @@ def pca_numpy(data):
--------
>>>
"""
from numpy import asarray
from scipy.linalg import svd # type: ignore

X = asarray(data)
n, dim = X.shape

Expand Down
4 changes: 2 additions & 2 deletions src/compas/geometry/trimesh_descent_numpy.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from numpy import asarray

from .trimesh_gradient_numpy import trimesh_gradient_numpy


Expand All @@ -17,6 +15,8 @@ def trimesh_descent_numpy(M):
The descent directions.
"""
from numpy import asarray

vertices, faces = M
V = asarray(vertices)
F = asarray(faces)
Expand Down
6 changes: 3 additions & 3 deletions src/compas/geometry/trimesh_gradient_numpy.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import numpy as np
from scipy.sparse import coo_matrix # type: ignore

from compas.linalg import normalizerow
from compas.linalg import normrow
from compas.linalg import rot90
Expand Down Expand Up @@ -29,6 +26,9 @@ def trimesh_gradient_numpy(M, rtype="array"):
and the coordinate difference vectors associated with the edges

"""
import numpy as np
from scipy.sparse import coo_matrix # type: ignore

V, F = M
v = V.shape[0]
f = F.shape[0]
Expand Down
15 changes: 8 additions & 7 deletions src/compas/geometry/trimesh_matrices_numpy.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
from numpy import asarray
from numpy import bincount
from numpy import cross
from numpy import zeros
from scipy.sparse import coo_matrix
from scipy.sparse import spdiags

from compas.geometry import cross_vectors
from compas.geometry import dot_vectors
from compas.geometry import length_vector
Expand Down Expand Up @@ -107,6 +100,8 @@ def trimesh_cotangent_laplacian_matrix(mesh, rtype="csr"):
`Laplacian Mesh Optimization <https://igl.ethz.ch/projects/Laplacian-mesh-processing/Laplacian-mesh-optimization/lmo.pdf>`_.

"""
from scipy.sparse import coo_matrix

vertex_index = mesh.vertex_index()
n = mesh.number_of_vertices()
data = []
Expand Down Expand Up @@ -173,6 +168,12 @@ def trimesh_vertexarea_matrix(mesh):
[0.1666, 0.1666, 0.1666]

"""
from numpy import asarray
from numpy import bincount
from numpy import cross
from numpy import zeros
from scipy.sparse import spdiags

vertex_index = mesh.vertex_index()
xyz = asarray(mesh.vertices_attributes("xyz"), dtype=float)
tris = asarray(
Expand Down
Loading