Reputation: 2152
I'm in the process of moving a significant application to Python from PHP. All is well, except one particular issue that I can't seem to get to the bottom of.
The old application uses a PHP library Image_3D to draw some cuboids to an image (SVG, though that's not important) and display them on the web page.
I've migrated almost everything to Flask(w/SQLAlchemy) except fo the imaging. I've tried matplotlib
, vpython
and almost got desperate enough to reach for OpenGL
bindings.
This is how PHP currently renders a few examples:
You can see that it remains readable enough even in extreme situations.
My best attempt at Python does fairly poorly:
(source: offblast.si)
(source: offblast.si)
The image is entirely unreadable. I didn't fill in the content, because, frankly, there's no point to it - you can't make anything out. Any attempt at fixing the view with ax.init_view
was even worse, no matter the elevation or azimuth.
The code is just a bunch of points, rendered with
fig = plt.figure(frameon=False)
ax = fig.gca(projection='3d')
ax.set_axis_off()
ax.set_aspect('equal')
ax.plot_wireframe(points[:, 0], points[:, 1], points[:, 2], color="b")
plt.savefig(filename, bbox_inches='tight', pad_inches=0)
I'm sure I'm doing something wrong, but I can't figure out how to make readable renders work in Python / matplotlib
or if there's a different library better suited for the task.
It occurs to me I haven't described the problem correctly - it's a business-restricted subset of the knapsack problem. The container and cuboids within are thus arbitrarily positioned. The visualization module recieves dimensions and positions and needs to render them. The regularity of the previous examples is just a first-order optimal solution and is found often, but not in the majority of situations.
Some more examples to illustrate:
A better solution with matplotlib
, folowing the answer below. It doesn't seem easy to get MPL to rotate the entire plot as to show a useful overview.
ax.view_init
should allow for changing the height, but it seems the FOV is too wide for such a narrow plot and all it does is transform the edges slightly.
(source: offblast.si)
Upvotes: 0
Views: 750
Reputation: 69242
You could use either VPython of matplotlib for this. In matplotlib I'd use a 3d box for your bars, and than another for the frame, and turn off the axes. Here's an examples:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection = "3d")
ax.autoscale(enable=False)
xpos = np.arange(5)
ypos = np.zeros(5)
zpos = np.zeros(5)
dx = np.ones(5)
dy = 5*np.ones(5)
dz = 5 + 5*np.random.random(5)
colors = ['r', 'c', 'g', 'y', 'm']
ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color=colors, alpha=1)
ax.bar3d(0, 0, 0, 5, 5, 25, color=(1, 1, 1, 0))
ax.set_axis_off()
plt.show()
Upvotes: 1