Skip to content

Commit

Permalink
Add transforms needed for Axes3D
Browse files Browse the repository at this point in the history
  • Loading branch information
AnsonTran committed May 3, 2024
1 parent 76efb2a commit af5946b
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/mpl_toolkits/mplot3d/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ python_sources = [
'axes3d.py',
'axis3d.py',
'proj3d.py',
'transform3d.py',
]

py3.install_sources(python_sources, subdir: 'mpl_toolkits/mplot3d')
Expand Down
96 changes: 96 additions & 0 deletions lib/mpl_toolkits/mplot3d/transform3d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import numpy as np
import matplotlib.transforms as mtransforms


class NonAffine3D(mtransforms.Transform):
input_dims = output_dims = 3
is_affine = False

def __init__(self, *args, matrix=None, **kwargs):
super().__init__(*args, **kwargs)
if matrix is None:
matrix = np.identity(4)
self._mtx = matrix.copy()
self._invalid = 0

def transform_non_affine(self, values):
mtx = self.get_matrix()

if isinstance(values, np.ma.MaskedArray):
tpoints = mtransforms.matrix_transform(values.data, mtx)
return np.ma.MaskedArray(tpoints, mask=np.ma.getmask(values))
return mtransforms.matrix_transform(values, mtx)

def inverted(self):
return NonAffine3D(matrix=np.linalg.inv(self._mtx))


class WorldTransform(mtransforms.Affine3D):
def __init__(self, xmin, xmax, ymin, ymax, zmin, zmax, pb_aspect=None):
dx = xmax - xmin
dy = ymax - ymin
dz = zmax - zmin
if pb_aspect is not None:
ax, ay, az = pb_aspect
dx /= ax
dy /= ay
dz /= az
mtx = np.array([
[1/dx, 0, 0, -xmin/dx],
[0, 1/dy, 0, -ymin/dy],
[0, 0, 1/dz, -zmin/dz],
[0, 0, 0, 1]
])
super().__init__(matrix=mtx)


class PerspectiveTransform(NonAffine3D):
def __init__(self, zfront, zback, focal_length):
e = focal_length
a = 1
b = (zfront + zback) / (zfront - zback)
c = -2 * (zfront * zback) / (zfront - zback)
mtx = np.array([[e, 0, 0, 0],
[0, e/a, 0, 0],
[0, 0, b, c],
[0, 0, -1, 0]])
super().__init__(matrix=mtx)


class OrthographicTransform(NonAffine3D):
def __init__(self, zfront, zback):
a = -(zfront + zback)
b = -(zfront - zback)
mtx = np.array([[2, 0, 0, 0],
[0, 2, 0, 0],
[0, 0, -2, 0],
[0, 0, a, b]])
super().__init__(matrix=mtx)


class ViewTransform(mtransforms.Affine3D):
def __init__(self, u, v, w, E):
"""
Return the view transformation matrix.
Parameters
----------
u : 3-element numpy array
Unit vector pointing towards the right of the screen.
v : 3-element numpy array
Unit vector pointing towards the top of the screen.
w : 3-element numpy array
Unit vector pointing out of the screen.
E : 3-element numpy array
The coordinates of the eye/camera.
"""
self._u = u
self._v = v
self._w = w

Mr = np.eye(4)
Mt = np.eye(4)
Mr[:3, :3] = [u, v, w]
Mt[:3, -1] = -E
mtx = np.dot(Mr, Mt)
super().__init__(matrix=mtx)

0 comments on commit af5946b

Please sign in to comment.