{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Intersecting planes\n\nThis examples demonstrates drawing intersecting planes in 3D. It is a generalization\nof :doc:`/gallery/mplot3d/imshow3d`.\n\nDrawing intersecting planes in `.mplot3d` is complicated, because `.mplot3d` is not a\nreal 3D renderer, but only projects the Artists into 3D and draws them in the right\norder. This does not work correctly if Artists overlap each other mutually. In this\nexample, we lift the problem of mutual overlap by segmenting the planes at their\nintersections, making four parts out of each plane.\n\nThis examples only works correctly for planes that cut each other in haves. This\nlimitation is intentional to keep the code more readable. Cutting at arbitrary\npositions would of course be possible but makes the code even more complex.\nThus, this example is more a demonstration of the concept how to work around\nlimitations of the 3D visualization, it's not a refined solution for drawing\narbitrary intersecting planes, which you can copy-and-paste as is.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\n\ndef plot_quadrants(ax, array, fixed_coord, cmap):\n \"\"\"For a given 3d *array* plot a plane with *fixed_coord*, using four quadrants.\"\"\"\n nx, ny, nz = array.shape\n index = {\n 'x': (nx // 2, slice(None), slice(None)),\n 'y': (slice(None), ny // 2, slice(None)),\n 'z': (slice(None), slice(None), nz // 2),\n }[fixed_coord]\n plane_data = array[index]\n\n n0, n1 = plane_data.shape\n quadrants = [\n plane_data[:n0 // 2, :n1 // 2],\n plane_data[:n0 // 2, n1 // 2:],\n plane_data[n0 // 2:, :n1 // 2],\n plane_data[n0 // 2:, n1 // 2:]\n ]\n\n min_val = array.min()\n max_val = array.max()\n\n cmap = plt.get_cmap(cmap)\n\n for i, quadrant in enumerate(quadrants):\n facecolors = cmap((quadrant - min_val) / (max_val - min_val))\n if fixed_coord == 'x':\n Y, Z = np.mgrid[0:ny // 2, 0:nz // 2]\n X = nx // 2 * np.ones_like(Y)\n Y_offset = (i // 2) * ny // 2\n Z_offset = (i % 2) * nz // 2\n ax.plot_surface(X, Y + Y_offset, Z + Z_offset, rstride=1, cstride=1,\n facecolors=facecolors, shade=False)\n elif fixed_coord == 'y':\n X, Z = np.mgrid[0:nx // 2, 0:nz // 2]\n Y = ny // 2 * np.ones_like(X)\n X_offset = (i // 2) * nx // 2\n Z_offset = (i % 2) * nz // 2\n ax.plot_surface(X + X_offset, Y, Z + Z_offset, rstride=1, cstride=1,\n facecolors=facecolors, shade=False)\n elif fixed_coord == 'z':\n X, Y = np.mgrid[0:nx // 2, 0:ny // 2]\n Z = nz // 2 * np.ones_like(X)\n X_offset = (i // 2) * nx // 2\n Y_offset = (i % 2) * ny // 2\n ax.plot_surface(X + X_offset, Y + Y_offset, Z, rstride=1, cstride=1,\n facecolors=facecolors, shade=False)\n\n\ndef figure_3D_array_slices(array, cmap=None):\n \"\"\"Plot a 3d array using three intersecting centered planes.\"\"\"\n fig = plt.figure()\n ax = fig.add_subplot(projection='3d')\n ax.set_box_aspect(array.shape)\n plot_quadrants(ax, array, 'x', cmap=cmap)\n plot_quadrants(ax, array, 'y', cmap=cmap)\n plot_quadrants(ax, array, 'z', cmap=cmap)\n return fig, ax\n\n\nnx, ny, nz = 70, 100, 50\nr_square = (np.mgrid[-1:1:1j * nx, -1:1:1j * ny, -1:1:1j * nz] ** 2).sum(0)\n\nfigure_3D_array_slices(r_square, cmap='viridis_r')\nplt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. tags::\n plot-type: 3D,\n level: advanced\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }