Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Orthographic projection for mplot3d #8326

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

Merged
merged 7 commits into from
Apr 10, 2017
Merged
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
3 changes: 3 additions & 0 deletions doc/users/whats_new/axes3d_orthographic_projection.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Orthographic projection for mplot3d
-----------------------------------
:class:`~mpl_toolkits.mplot3d.axes3d.Axes3D` now accepts ``proj_type`` kwarg and has a method :meth:`~mpl_toolkits.mplot3d.axes3d.Axes3D.set_proj_type`. The default option is ``'persp'`` as before, and supplying ``'ortho'`` enables orthographic view.
23 changes: 21 additions & 2 deletions lib/mpl_toolkits/mplot3d/axes3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def __init__(self, fig, rect=None, *args, **kwargs):
*elev* Elevation viewing angle (default 30)
*zscale* [%(scale)s]
*sharez* Other axes to share z-limits with
*proj_type* 'persp' or 'ortho' (default 'persp')
================ =========================================

.. versionadded :: 1.2.1
Expand All @@ -78,6 +79,7 @@ def __init__(self, fig, rect=None, *args, **kwargs):
self.initial_elev = kwargs.pop('elev', 30)
zscale = kwargs.pop('zscale', None)
sharez = kwargs.pop('sharez', None)
self.set_proj_type(kwargs.pop('proj_type', 'persp'))

self.xy_viewLim = unit_bbox()
self.zz_viewLim = unit_bbox()
Expand Down Expand Up @@ -959,6 +961,23 @@ def view_init(self, elev=None, azim=None):
else:
self.azim = azim

def set_proj_type(self, proj_type):
"""
Set the projection type.

Parameters
----------
proj_type : str
Type of projection, accepts 'persp' and 'ortho'.

"""
if proj_type == 'persp':
self._projection = proj3d.persp_transformation
elif proj_type == 'ortho':
self._projection = proj3d.ortho_transformation
else:
raise ValueError("unrecognized projection: %s" % proj_type)

def get_proj(self):
"""
Create the projection matrix from the current viewing position.
Expand Down Expand Up @@ -1001,9 +1020,9 @@ def get_proj(self):
zfront, zback = -self.dist, self.dist

viewM = proj3d.view_transformation(E, R, V)
perspM = proj3d.persp_transformation(zfront, zback)
projM = self._projection(zfront, zback)
M0 = np.dot(viewM, worldM)
M = np.dot(perspM, M0)
M = np.dot(projM, M0)
return M

def mouse_init(self, rotate_btn=1, zoom_btn=3):
Expand Down
10 changes: 10 additions & 0 deletions lib/mpl_toolkits/mplot3d/proj3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ def persp_transformation(zfront, zback):
[0,0,-1,0]
])

def ortho_transformation(zfront, zback):
# note: w component in the resulting vector will be (zback-zfront), not 1
a = -(zfront + zback)
b = -(zfront - zback)
return np.array([[2,0,0,0],
[0,2,0,0],
[0,0,-2,0],
[0,0,a,b]
])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you provide a reference for this formulation? I am not an expert in 3d transforms, but this doesn't match anything I am seeing on the wikipedia page for orthographic projection.

Copy link
Contributor Author

@txxia txxia Mar 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I should have justified it.
This matrix is almost equivalent to the one in the Wikipedia page. Based on persp_transformation, I made these assumptions:

  • zfront is the value for near, left and bottom
  • zback for far, right, top
  • the X and Y translations are omitted (I guess so the image will always be centered at the origin)

It's a simple derivation from the one from Wikipedia (v1), but since v2 and v1 are equivalent in homogeneous coordinates, I thought the second will look nicer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, and if I transpose that, it then matches up. Got it. Well, just include some notes about it in comments for some future poor soul.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this the transpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because numpy matrix is in row major order?


def proj_transform_vec(vec, M):
vecw = np.dot(M, vec)
w = vecw[3]
Expand Down
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading