How draw implict 3D surface with sympy? - sympy

I try to draw x**2 + y**3 = z**2 use sympy, but I don't how to draw it.
I use plot3d(x**2 + y**3-z**2) but it don't work at all, So can someone know how to do?

Sadly, Sympy doesn't support 3d implicit plots. However, sage does, though I remember it was a very heavy module to install.
Alternatively, if you are using Jupyter Notebook you can use K3D-Jupyter which is capable of plotting implicit surfaces. Let's see how to plot your surface:
import k3d
import numpy as np
r = 5
zmin, zmax = -r, r
xmin, xmax = -r, r
ymin, ymax = -r, r
Nx, Ny, Nz = 100, 100, 100
x = np.linspace(xmin, xmax, Nx, dtype=np.float32)
y = np.linspace(ymin, ymax, Ny, dtype=np.float32)
z = np.linspace(zmin, zmax, Nz, dtype=np.float32)
x, y, z = np.meshgrid(x, y, z, indexing='ij')
p = x**2 + y**3 - z**2
plot = k3d.plot()
plt_iso = k3d.marching_cubes(p, compression_level=9, xmin=xmin, xmax=xmax,
ymin=ymin, ymax=ymax,
zmin=zmin, zmax=zmax, level=0.0,
flat_shading=False)
plot += plt_iso
plot.display()

Related

plt.imshow() but axes of real units, automatic "even" tick locations by Matplotlib? [duplicate]

This question already has answers here:
how to use 'extent' in matplotlib.pyplot.imshow
(2 answers)
Matplotlib: how to make imshow read x,y coordinates from other numpy arrays?
(4 answers)
Closed 4 years ago.
I'm using .imshow() to show a 2D array from Z(X, Y), and I would like the axes to reflect the original x and y values used for the function, instead of the array indices.
But I would like Matplotlib to use it's tick marking algorithm to places ticks at "nice" numbers. Below I show what those might look like.
One way to do this would be to "extract" the tick mars from the two 1D plots and "implant" them on the imshow, but I don't know how to do that.
I've tried some searching but I can't even think of good matplotlib search terms to describe what I need.
def Z(X, Y):
Rsq = X**2 + Y**2 - 0.025*X**4
return np.exp(-0.2*Rsq)*np.cos(2.*Rsq)
import numpy as np
import matplotlib.pyplot as plt
halfpi, pi, threehalfpi, twopi = [f*np.pi for f in (0.5, 1, 1.5, 2)]
x = np.linspace(-twopi, pi, 450)
y = np.linspace(-threehalfpi, pi, 350)
X, Y = np.meshgrid(x, y, indexing='xy')
z1 = Z(X, Y)
z2 = Z(x, 0)
z3 = Z(0, y)
fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 2)
ax1.imshow(z1, origin='lower')
ax1.xaxis.tick_top()
ax1.yaxis.tick_right()
plt.tick_params(axis='both', which='major', labelsize=14)
ax2 = fig.add_subplot(2, 2, 4)
ax2.plot(x, z2)
ax2.set_xlim(x.min(), x.max())
ax2.xaxis.tick_top()
ax2.yaxis.tick_right()
plt.tick_params(axis='both', which='major', labelsize=14)
ax3 = fig.add_subplot(2, 2, 1)
ax3.plot(z3, y)
ax3.set_ylim(y.min(), y.max())
ax3.yaxis.tick_right()
plt.tick_params(axis='both', which='major', labelsize=14)
plt.show()
print 'x: ', x.min(), x.max()
print 'y: ', y.min(), y.max()
You can set the ticklabels:
delta_x = x[1] - x[0] # get the spacing of your data points
xticks = ax.get_xticks()
ax.set_xticklabels(xticks * delta_x)
and the same for y.

Draw Isometric figure based on matrix

How can generate a isometric from a matrix with numbers??
I need ideas
Example:
Matrix:
[[3,2],
[1,1]]
This
Each number is the height, 3 represent 3 cubes height first file, 2 represent 2 cubes height first file second element
Thanks
This is a very nice question.
I think matplotlib does not directly provide any such function, but we can of course simulate a cube by its six surfaces. Getting those surfaces we can use a piece of code provided here.
We then need to plot the cube at the positions defined by the matrix.
In order to make the plot look isometric, we use a workaround, plotting invisible points at the corners of the cubic bounding box of the mpl3d axes.
Finally we need to make the axes invisible.
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
def cuboid_data(center, size=(1,1,1)):
# code taken from
# https://stackoverflow.com/questions/30715083/python-plotting-a-wireframe-3d-cuboid?noredirect=1&lq=1
# suppose axis direction: x: to left; y: to inside; z: to upper
# get the (left, outside, bottom) point
o = [a - b / 2 for a, b in zip(center, size)]
# get the length, width, and height
l, w, h = size
x = [[o[0], o[0] + l, o[0] + l, o[0], o[0]], # x coordinate of points in bottom surface
[o[0], o[0] + l, o[0] + l, o[0], o[0]], # x coordinate of points in upper surface
[o[0], o[0] + l, o[0] + l, o[0], o[0]], # x coordinate of points in outside surface
[o[0], o[0] + l, o[0] + l, o[0], o[0]]] # x coordinate of points in inside surface
y = [[o[1], o[1], o[1] + w, o[1] + w, o[1]], # y coordinate of points in bottom surface
[o[1], o[1], o[1] + w, o[1] + w, o[1]], # y coordinate of points in upper surface
[o[1], o[1], o[1], o[1], o[1]], # y coordinate of points in outside surface
[o[1] + w, o[1] + w, o[1] + w, o[1] + w, o[1] + w]] # y coordinate of points in inside surface
z = [[o[2], o[2], o[2], o[2], o[2]], # z coordinate of points in bottom surface
[o[2] + h, o[2] + h, o[2] + h, o[2] + h, o[2] + h], # z coordinate of points in upper surface
[o[2], o[2], o[2] + h, o[2] + h, o[2]], # z coordinate of points in outside surface
[o[2], o[2], o[2] + h, o[2] + h, o[2]]] # z coordinate of points in inside surface
return x, y, z
def plotCubeAt(pos=(0,0), N=0, ax=None):
# Plotting N cube elements at position pos
if ax !=None:
if N > 0:
for n in range(N):
X, Y, Z = cuboid_data( (pos[0],pos[1],n) )
ax.plot_surface(X, Y, Z, color='b', rstride=1, cstride=1, alpha=1)
def plotIsoMatrix(ax, matrix):
# plot a Matrix
# where matrix[i,j] cubes are added at position (i,j)
for i in range(matrix.shape[0]):
for j in range(matrix.shape[1]):
plotCubeAt(pos=(i,j), N=matrix[i,j], ax=ax)
l = max(matrix.shape[0], matrix.shape[1], matrix.max())
bb = np.array([(0,0,0), (0,l,0), (l,0,0), (l,l,0),(0,0,l), (0,l,l), (l,0,l), (l,l,l)])
ax.plot(bb[:,0], bb[:,1], bb[:,2], "w", alpha=0.0)
if __name__ == '__main__':
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect('equal')
matrix = np.array([[3,2],[1,1]])
plotIsoMatrix(ax, matrix)
ax.set_axis_off()
plt.show()

Matrix related calculation in python

I am finding a very interesting problem while calculating a matrix update in python . I have to calculate the error (which is difference between previous n updated matrix ).
import numpy as np
import matplotlib.pyplot as plt
#from matplotlib import animation
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
def update(A):
C=A
D=A
D[1:-1,1:-1]=(C[0:-2,1:-1]+C[2:,1:-1]+C[1:-1,0:-2]+C[1:-1,2:])/4
return(np.abs(D-C),D)
def error(A,B):
C=np.zeros(np.shape(A),np.float64)
#e=np.max(np.max(np.abs(C)))
e=(np.abs(C))
return (e.sum(dtype='float64'))
def initial(C):
C[0,:]=0 ## Top Boundary
C[-1,:]=0 ## Bottom Boundary
C[:,0]=0 ## left Boundary
C[:,-1]=100 ## Right Boundary
return(C)
def SolveLaplace(nx, ny,epsilon,imax):
## Initialize the mesh with some values
U = np.zeros((nx, ny),np.float64)
## Set boundary conditions for the problem
U=initial(U)
## Store previous grid values to check against error tolerance
UN=np.zeros((nx, ny),np.float64)
UN=initial(UN)
## Constants
k = 1 ## Iteration counter
## Iterative procedure
while k<imax:
err,U=update(U)
print(err.sum())
k+=1
return (U)
nx = 50.0
ny = 50.0
dx = 0.001
epsilon = 1e-6 ## Absolute Error tolerance
imax = 5000 ## Maximum number of iterations allowed
Z = SolveLaplace(nx, ny,epsilon,imax)
#x = np.linspace(0, nx * dx, nx)
#y = np.linspace(0, ny * dx, ny)
#X, Y = np.meshgrid(x,y)
##===================================================================
def PlotSolution(nx,ny,dx,T):
## Set up x and y vectors for meshgrid
x = np.linspace(0, nx * dx, nx)
y = np.linspace(0, ny * dx, ny)
fig = plt.figure()
ax = fig.gca(projection='3d')
X, Y = np.meshgrid(x,y)
ax.plot_surface(X, Y, T.transpose(), rstride=1, cstride=1, cmap=cm.cool, linewidth=0, antialiased=False)
plt.xlabel("X")
plt.ylabel("Y")
#plt.zlabel("T(X,Y)")
plt.figure()
plt.contourf(X, Y, T.transpose(), 32, rstride=1, cstride=1, cmap=cm.cool)
plt.colorbar()
plt.xlabel("X")
plt.ylabel("Y")
plt.show()
##===================================================================
PlotSolution(nx, ny, dx, Z)
I am suppose to solve Laplace equation for 2-d sheet(temperature distribution) and when error is less than certain minimum value ,equilibrium will be achieved. But while calculating error, I am always getting 0 but when I print my matrix then I find it should not be a zero . Guys I think I have some conceptual problem here and So please help .
Your problem is that you use shallow copies, i.e., only copy the reference, when assigning C=A; D=A in the update function. Essentially, after the construction of D, all three variables A,C,D point to the same object. Use
def update(A):
C=1.0*A
D=1.0*A
D[1:-1,1:-1]=(C[0:-2,1:-1]+C[2:,1:-1]+C[1:-1,0:-2]+C[1:-1,2:])/4
return(np.abs(D-C),D)
or even shorter
def update(A):
D=A.copy()
D[1:-1,1:-1]=(A[0:-2,1:-1]+A[2:,1:-1]+A[1:-1,0:-2]+A[1:-1,2:])/4
return(np.abs(D-A),D)
Passing arguments and performing arithmetic operations results automatically in a deep copy.
You know that the (geometric, first order) convergence rate is something like max(1-C/(nx^2), 1-C/(ny^2)), i.e., very slow for even moderately large grids? For real applications, better use conjugate gradients, other Krylov-related algorithms or multi-grid approaches (or sparse solver libraries, UMFpack ...).
In the (unused) error procedure, should there be not something like
e = abs(A-B)
At the moment, you return the norm of the freshly generated zero matrix C.

Perspective Projection onto y/z plane

So this wikipedia page shows you how to make a perspective projection of a point in 3d space onto the x/y plane. Does anyone know how to do the equivalent onto the y/z plane? This is what I am doing right now (just the wikipedia pages stuff.):
class Shape(object):
...
def apply_perspective(self, camera_pos, orientation, viewer_pos):
a, b, c = viewer_pos
cx, cy, cz = map(cos, orientation)
sx, sy, sz = map(sin, orientation)
transformed_vertices = []
append = transformed_vertices.append
for v in self.vertices:
x, y, z = v - camera_pos
t1 = sz*y + cz*x
t2 = cz*y - sz*x
x_ = cy*t1 - sy*z
t3 = cy*z + sy*t1
y_ = sx*t3 + cx*t2
z_ = cx*t3 - sx*t2
t4 = c/z_
newx = t4*x_ - a
newy = t4*y_ - b
append((newx, newy))
return transformed_vertices
You can see all of the code at in the github repo.The file in particular that this is in is shapes.py .
I ended up making a guess that turned out to be correct. I used t4 = a/x_, newx = t4*y_ - b, and newy = t4*z_ - c; which turned out to be correct. I just used algebra!

Efficient way to get the angle between two vectors in a single plane?

If I know for a fact that the x and z values of the vectors will be identical,
therefore im only concerned in measuring the 'vertical' angle of from the differences in the y plane, is there a more efficient method to do this compared to computing the dot product?
My current code using the dot product method is as follows:
float a_mag = a.magnitude();
float b_mag = b.magnitude();
float ab_dot = a.dot(b);
float c = ab_dot / (a_mag * b_mag);
// clamp d to from going beyond +/- 1 as acos(+1/-1) results in infinity
if (c > 1.0f) {
c = 1.0;
} else if (c < -1.0) {
c = -1.0;
}
return acos(c);
I would love to be able to get rid of these square roots
Suppose that your two vectors live at u = (x, y1, z) and v = (x, y2, z), and you're interested in the planar angle between the two along the plane spanned by the two vectors. You'd have to compute the dot product and the magnitude, but you can save a few operations:
u.v = x.x + y1.y2 + z.z
u^2 = x.x + y1.y1 + z.z
v^2 = x.x + y2.y2 + z.z
So we should precompute:
float xz = x*x + z*z, y11 = y1*y1, y12 = y1*y2, y22 = y2*y2;
float cosangle = (xz + y12) / sqrt((xz + y11) * (xz + y22));
float angle = acos(cosangle);
If the values of x and z are unchanged, then the calculation is very easy: just use basic trigonometry.
Let the points be (x, y1, z) and (x, y2, z). You can find out the angle a vector makes with the ZX-plane. Let the angles be t1 and t2 respectively. Then:
w = sqrt(x^2 + z^2)
tan(t1) = y1 / w
So t1 = atan(y1 / w)
Similarly t2 = atan(y2 / w)
The angle is (t2 - t1)
There's one pitfall: When both x and z are zero, the tans are undefined... but such a trivial case can easily be handled separately.
Unfortunately, there seems to be no way to avoid the square root.