In this old answer of mine, I used Asymptote to diagram numerous intersecting planes bound by a cube: https://tex.stackexchange.com/a/733960/319072.
I want to be able to do this in TikZ or MetaPost. There are solutions for two or three intersecting planes, but I haven't found one which handles more than three.
That is the goal of this question. How can you draw more than three intersecting planes which are bounded by a cube, in a 2D software?
(The real goal of this question is to share this achievement, and to inspire others in the community to take a stab at this, possibly with different techniques, hence my self-answer.)
MWE:
unitsize(1cm); import three; import graph3; // Function to sort points based on the angle with the centroid triple[] sort_points(triple[] points) { triple centroid = (0, 0, 0); for (int i = 0; i < points.length; ++i) { centroid += points[i]; } centroid /= points.length; real[] angles; for (int i = 0; i < points.length; ++i) { angles.push(atan2(points[i].y - centroid.y, points[i].x - centroid.x)); } for (int i = 0; i < points.length; ++i) { for (int j = i + 1; j < points.length; ++j) { if (angles[i] > angles[j]) { real temp_angle = angles[i]; angles[i] = angles[j]; angles[j] = temp_angle; triple temp_point = points[i]; points[i] = points[j]; points[j] = temp_point; } } } return points; } void draw_plane( triple normal_vector ,triple point_on_plane ,real xmin = -5 ,real xmax = 5 ,real ymin = -5 ,real ymax = 5 ,real zmin = -5 ,real zmax = 5 ,pen thecolor = white ,real theopacity = 0.3 ,bool drawthebox = false ) { if (drawthebox) { draw(box((xmin,ymin,zmin), (xmax,ymax,zmax))); } real a = normal_vector.x; real b = normal_vector.y; real c = normal_vector.z; real d = dot(normal_vector, point_on_plane); real x(real y, real z) { return (((d)-((b)*(y))-((c)*(z)))/(a)); } real y(real x, real z) { return (((d)-((a)*(x))-((c)*(z)))/(b)); } real z(real x, real y) { return (((d)-((a)*(x))-((b)*(y)))/(c)); } if (a==0 && b==0 && c==0) { draw( surface( (xmin,ymin,zmin) -- (xmax,ymin,zmin) -- (xmax,ymax,zmin) -- (xmin,ymax,zmin) -- cycle ) ,thecolor+opacity(theopacity) ); draw( surface( (xmin,ymin,zmax) -- (xmax,ymin,zmax) -- (xmax,ymax,zmax) -- (xmin,ymax,zmax) -- cycle ) ,thecolor+opacity(theopacity) ); draw( surface( (xmin,ymin,zmin) -- (xmax,ymin,zmin) -- (xmax,ymin,zmax) -- (xmin,ymin,zmax) -- cycle ) ,thecolor+opacity(theopacity) ); draw( surface( (xmin,ymax,zmin) -- (xmax,ymax,zmin) -- (xmax,ymax,zmax) -- (xmin,ymax,zmax) -- cycle ) ,thecolor+opacity(theopacity) ); draw( surface( (xmin,ymin,zmin) -- (xmin,ymax,zmin) -- (xmin,ymax,zmax) -- (xmin,ymin,zmax) -- cycle ) ,thecolor+opacity(theopacity) ); draw( surface( (xmax,ymin,zmin) -- (xmax,ymax,zmin) -- (xmax,ymax,zmax) -- (xmax,ymin,zmax) -- cycle ) ,thecolor+opacity(theopacity) ); } // yz planes if (a!=0 && b==0 &&c==0) { if (xmin<=d/a && d/a<=xmax) { draw( surface( (x(ymin,zmin),ymin,zmin) -- (x(ymax,zmin),ymax,zmin) -- (x(ymax,zmax),ymax,zmax) -- (x(ymin,zmax),ymin,zmax) -- cycle ) ,thecolor+opacity(theopacity) ); } } // xz planes if (a==0 & b!=0 & c==0) { if (ymin<=d/b && d/b<=ymax) { draw( surface( (xmin,y(xmin,zmin),zmin) -- (xmax,y(xmax,zmin),zmin) -- (xmax,y(xmax,zmax),zmax) -- (xmin,y(xmin,zmax),zmax) -- cycle ) ,thecolor+opacity(theopacity) ); } } // xy planes if (a==0 && b==0 & c!=0) { if (zmin<=d/c && d/c<=zmax) { draw( surface( (xmin,ymin,z(xmin,ymin)) -- (xmax,ymin,z(xmax,ymin)) -- (xmax,ymax,z(xmax,ymax)) -- (xmin,ymax,z(xmin,ymax)) -- cycle ) ,thecolor+opacity(theopacity) ); } } // y of x planes (invariant over z) if (a!=0 && b!=0 && c==0) { real xylower = xmin; if (ymax < y(xmin,0)) { xylower = x(ymax,0); } if (y(xmin,0) < ymin) { xylower = x(ymin,0); } real xyupper = xmax; if (ymax < y(xmax,0)) { xyupper = x(ymax,0); } if (y(xmax,0) < ymin) { xylower = x(ymin,0); } if (!(xylower<xmin || xmax<xylower) && !(xyupper<xmin || xmax<xyupper)) { draw( surface( (xylower,y(xylower,0),zmin) -- (xyupper,y(xyupper,0),zmin) -- (xyupper,y(xyupper,0),zmax) -- (xylower,y(xylower,0),zmax) -- cycle ) ,thecolor+opacity(theopacity) ); } } // z of x planes (invariant over y) if (a!=0 && b==0 && c!=0) { real xzlower = xmin; if (z(xmin,0)<zmin) { xzlower = x(0,zmin); } if (zmax<z(xmin,0)) { xzlower = x(0,zmax); } real xzupper = xmax; if (z(xmax,0)<zmin) { xzupper = x(0,zmin); } if (zmax<z(xmax,0)) { xzupper = x(0,zmax); } if (!(xzlower<xmin || xzlower>xmax) && !(xzupper<xmin || xzupper>xmax)) { draw( surface( (xzlower,ymin,z(xzlower,0)) -- (xzupper,ymin,z(xzupper,0)) -- (xzupper,ymax,z(xzupper,0)) -- (xzlower,ymax,z(xzlower,0)) -- cycle ) ,thecolor+opacity(theopacity) ); } } // z of y planes (invariant over x) if (a==0 && b!=0 && c!=0) { real yzlower = ymin; if (z(0,ymin)<zmin) { yzlower = y(0,zmin); } if (zmax<z(0,ymin)) { yzlower = y(0,zmax); } real yzupper = ymax; if (z(0,ymax)<zmin) { yzupper = y(0,zmin); } if (zmax<z(0,ymax)) { yzupper = y(0,zmax); } if (!(yzlower<ymin || yzlower>ymax) && !(yzupper<ymin || yzupper>ymax)) { draw( surface( (xmin,yzlower,z(0,yzlower)) -- (xmin,yzupper,z(0,yzupper)) -- (xmax,yzupper,z(0,yzupper)) -- (xmax,yzlower,z(0,yzlower)) -- cycle ) ,thecolor+opacity(theopacity) ); } } // Intersection points array triple[] intersections; // Calculate intersections with x, y, z bounds void add_intersection(real x, real y, real z) { if (xmin <= x && x <= xmax && ymin <= y && y <= ymax && zmin <= z && z <= zmax) { intersections.push((x, y, z)); } } // Add intersections with the six planes of the rectangular prism for (real y = ymin; y <= ymax; y += ymax - ymin) { for (real z = zmin; z <= zmax; z += zmax - zmin) { add_intersection(x(y, z), y, z); } } for (real x = xmin; x <= xmax; x += xmax - xmin) { for (real z = zmin; z <= zmax; z += zmax - zmin) { add_intersection(x, y(x, z), z); } } for (real x = xmin; x <= xmax; x += xmax - xmin) { for (real y = ymin; y <= ymax; y += ymax - ymin) { add_intersection(x, y, z(x, y)); } } // Sort intersections intersections = sort_points(intersections); // Initialize plane_outline with the first intersection point path3 plane_outline; if (intersections.length > 0) { plane_outline = (intersections[0]); } // Convert intersections to a path for (int i = 1; i < intersections.length; ++i) { plane_outline = plane_outline -- intersections[i]; } // Close the path if we have enough points if (intersections.length >= 3) { plane_outline = plane_outline -- cycle; } // Draw the outline of the clipped plane if (intersections.length >= 3) { draw(surface(plane_outline), thecolor + opacity(theopacity)); } } void draw_plane_test() { // (a==0 && b==0 && c==0) // draw_plane( // (0,0,0) // ,(0,0,0) // ,thecolor=blue // ,theopacity=0.1 // ,drawthebox=true // ); // (a!=0 && b==0 && c==0) // draw_plane( // (-2,0,0) // ,(-1,-1,-1) // ,thecolor=red // ); // draw_plane( // (3,0,0) // ,(3,2,1) // ,thecolor=red // ); // (a==0 && b!=0 && c==0) // draw_plane( // (0,2,0) // ,(2,-2,2) // ,thecolor=blue // ); // draw_plane( // (0,-3,0) // ,(1,5,2) // ,thecolor=blue // ); // (a==0 && b==0 && c!=0) // draw_plane( // (0,0,1) // ,(2,-2,2) // ,thecolor=green // ); // draw_plane( // (0,0,-2) // ,(1,5,1) // ,thecolor=green // ); // (a!=0 && b!=0 && c==0) // draw_plane( // (1,2,0) // ,(3,3,3) // ,thecolor=red // ,drawthebox=true // ); // draw_plane( // (-1,2,0) // ,(3,3,3) // ,thecolor=red // ); // draw_plane( // (20,-3,0) // ,(-3,-2,-4) // ,thecolor=red // ); // (a!=0 && b==0 && c!=0) // draw_plane( // (-2,0,3) // ,(0,0,0) // ,thecolor=green // ,drawthebox=true // ); // draw_plane( // (-4,0,-3) // ,(2,2,2) // ,thecolor=green // ,drawthebox=true // ); // draw_plane( // (4,0,30) // ,(-2,3,-2) // ,thecolor=green // ,drawthebox=true // ); // (a==0 && b!=0 && c!=0) // draw_plane( // (0,-2,3) // ,(0,0,0) // ,thecolor=blue // ,drawthebox=true // ); // draw_plane( // (0,-4,-3) // ,(2,2,2) // ,thecolor=blue // ,drawthebox=true // ); // draw_plane( // (0,4,30) // ,(3,-2,-2) // ,thecolor=blue // ,drawthebox=true // ); // (a!=0 && b!=0 && c!=0) draw_plane( (2,2,2) ,(-3,4,1) ,thecolor=red ,drawthebox=true ); draw_plane( (-2,-3,1) ,(-3,4,1) ,thecolor=green ); draw_plane( (-2,-3,1) ,(3,3,-1) ,thecolor=blue ); } draw_plane_test(); 
