{"id":7891,"date":"2021-12-06T14:30:45","date_gmt":"2021-12-06T19:30:45","guid":{"rendered":"https:\/\/blogs.mathworks.com\/cleve\/?p=7891"},"modified":"2021-12-06T17:59:54","modified_gmt":"2021-12-06T22:59:54","slug":"the-menger-sponge-fractal","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/cleve\/2021\/12\/06\/the-menger-sponge-fractal\/","title":{"rendered":"The Menger Sponge Fractal"},"content":{"rendered":"\r\n\r\n<div class=\"content\"><!--introduction--><p>The Menger sponge is a popular fractal that generalizes Cantor sets and Sierpinski triangles. Its fractal dimension is between two and three.<\/p><!--\/introduction--><h3>Contents<\/h3><div><ul><li><a href=\"#13bad8e5-da2a-4c21-9984-f9c947a9c04e\">Karl Menger<\/a><\/li><li><a href=\"#bb901c74-c0df-4de9-8cd5-151933ad2649\">The Sponge<\/a><\/li><li><a href=\"#d9cd20cb-600a-4753-8058-52ca4e93a783\">What about the next level?<\/a><\/li><li><a href=\"#bc0498a8-fcb8-4bdc-890c-aef3620f7fb0\">Two- or three-dimensional?<\/a><\/li><li><a href=\"#b4fd875e-5bb2-46e0-b322-0e61d6c0bbc7\">Light on the subject.<\/a><\/li><li><a href=\"#e119fcd2-aa93-4aff-a20f-2f34234fa3c9\">Tilt<\/a><\/li><li><a href=\"#b643f243-1a87-460f-8472-8a7d6816198b\">Animation<\/a><\/li><li><a href=\"#54943f6f-a802-4319-b292-b23915c5dd83\"><tt>menger<\/tt><\/a><\/li><li><a href=\"#5167aba7-028f-4804-88ae-00ce1e6e1fe7\"><tt>sponge<\/tt><\/a><\/li><li><a href=\"#c9ada87e-ef74-4474-a4eb-081c12c2b356\"><tt>cube<\/tt><\/a><\/li><li><a href=\"#ec0270ea-6840-4e49-b600-33a47bb84c4c\"><tt>init_fig<\/tt><\/a><\/li><li><a href=\"#53650df7-81e3-43b1-ba02-08171bde54e8\"><tt>wbmf<\/tt><\/a><\/li><li><a href=\"#3138c9d6-748e-43d4-a279-2943d1e1b839\">Software<\/a><\/li><li><a href=\"#fbfa6b1d-3e8f-4a8c-bd02-11d249bf4f3f\">Learn more<\/a><\/li><li><a href=\"#fef02937-e0ea-4374-a130-63bab944dce7\">Thanks<\/a><\/li><\/ul><\/div><h4>Karl Menger<a name=\"13bad8e5-da2a-4c21-9984-f9c947a9c04e\"><\/a><\/h4><p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Karl_Menger\">Karl Menger<\/a> (1902-1985) was a 20th-century Austrian-American mathematician.  Most of his career was at the Illinois Institute of Technology in Chicago.  He made contributions to geometry and game theory.  But he is best known for his cube-like fractal known as a \"sponge\".<\/p><h4>The Sponge<a name=\"bb901c74-c0df-4de9-8cd5-151933ad2649\"><\/a><\/h4><p>Start with a big solid cube.  This is level zero.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_sponge00.png\" alt=\"\"> <\/p><p>Trisect the big cube into 3x3x3 = 27 smaller cubes, like a Rubik's cube without the labels.  Remove the center cube from each of the six faces and the cube at the very center.  That leaves these 27 - 7 = 20 smaller cubes at level one.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_sponge01.png\" alt=\"\"> <\/p><p>Repeat the process on each of these 20 cubes to generate 20x20 = 400 even smaller cubes at level two.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_sponge02.png\" alt=\"\"> <\/p><p>Once more.  This is level three with 800 tiny cubes and lots of holes.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_sponge03.png\" alt=\"\"> <\/p><h4>What about the next level?<a name=\"d9cd20cb-600a-4753-8058-52ca4e93a783\"><\/a><\/h4><p>With the resolution available on our computer screens, or on a printed page, there is little to be gained by  going beyond level three. Each cube occupies only a few pixels and the level four cubes would be 20 times smaller.<\/p><p>And there are 20 times as many of  them.  That's 160,000 subpixel sized cubes. Even though I wasn't going to be able to view it, I did complete one computation at level four.  It requiries more main memory than the 32 gigabytes of RAM that I have on my laptop.  It had to use virtual storage and ran for almost 15 minutes.<\/p><h4>Two- or three-dimensional?<a name=\"bc0498a8-fcb8-4bdc-890c-aef3620f7fb0\"><\/a><\/h4><p>The solid volume is reduced by a factor of 20\/27 at each level. So if you theoretically keep going past level three or four, the volume approaches zero. On the other hand, the surface area becomes infinite. The result is a fractal that is somewhere between two- and three-dimensional. In 1918, Felix Hausdorff introduced <i>fractal dimension<\/i>. It turns out that the Menger sponge has Hausdorff dimension log(20)\/log(3), which is about 2.727.<\/p><h4>Light on the subject.<a name=\"b4fd875e-5bb2-46e0-b322-0e61d6c0bbc7\"><\/a><\/h4><p>So far, we've been working in the dark.  Let's shed some light on the subject.  The big cube we started with is actually (a simulation of) solid gold.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_sponge10.png\" alt=\"\"> <\/p><p>The light strikes various surfaces at different angles to produce different shades of gold.  We can now easily see the holes.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_sponge11.png\" alt=\"\"> <\/p><p>At level two we have carved out almost half of the gold.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_sponge12.png\" alt=\"\"> <\/p><p>With the light and shading, level three takes about five seconds to compute and plot.  It is somewhat darker than the other plots because the cubes edges are beginning to dominate.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_sponge13.png\" alt=\"\"> <\/p><h4>Tilt<a name=\"e119fcd2-aa93-4aff-a20f-2f34234fa3c9\"><\/a><\/h4><p>If you tilt the sponge very slightly, you can see that the holes are channels passing all the way through.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_tilt.png\" alt=\"\"> <\/p><h4>Animation<a name=\"b643f243-1a87-460f-8472-8a7d6816198b\"><\/a><\/h4><p>I try to have animated .gifs in all of my blog posts.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/sponges.gif\" alt=\"\"> <\/p><h4><tt>menger<\/tt><a name=\"54943f6f-a802-4319-b292-b23915c5dd83\"><\/a><\/h4><p>Here is my code.  The function <tt>menger<\/tt> gets things started.  There are two input parameters.  The first specifies the desired level of refinement.  A single solid cube is <tt>level<\/tt> = 0.  Increasing <tt>level<\/tt> by one multiplies the number of cubes, and consequently both the execution time and the memory required, by a factor of 20. Any <tt>level<\/tt> greater than 3 is impractical.<\/p><p>The second input parameter is true or false.  True turns on a <tt>camlight<\/tt> so you can see more detail.  With false there is no lighting.  Lighting takes more time, especially if you expect to manipulate the sponge after it has been computed.<\/p><p>The 8-by-3 array <tt>V<\/tt> provides the vertices of a cube of half-width 3. Starting with this width means that many of the subsequent computations are done with no roundoff error.  This is important when the size of the cubes approaches the graphics resolution.<\/p><pre class=\"language-matlab\"><span class=\"keyword\">function<\/span> menger(level,lit)\r\n    <span class=\"comment\">% Fractal cube, the Menger sponge.<\/span>\r\n    <span class=\"comment\">% menger(level) generates 20^level cubes.<\/span>\r\n    <span class=\"comment\">% menger(level,true) is illuminated.<\/span>\r\n    <span class=\"comment\">% menger(level,false) is not illuminated, so it is faster.<\/span>\r\n<\/pre><pre>     V = [-3 -3 -3; -3 -3 3; -3 3 -3; -3 3 3;\r\n           3 -3 -3;  3 -3 3;  3 3 -3;  3 3 3];\r\n     init_fig(lit)\r\n     sponge(V,level)\r\n end<\/pre><h4><tt>sponge<\/tt><a name=\"5167aba7-028f-4804-88ae-00ce1e6e1fe7\"><\/a><\/h4><p>This is where all the action takes place. The function <tt>sponge<\/tt> is recursive.  It calls itself repeatedly, passing arrays <tt>v<\/tt> representing the vertices of small cubes. The <tt>v<\/tt> arrays are obtained from the original <tt>V<\/tt> by scaling with inverse powers of 3 and translating with vectors <tt>[x y z]<\/tt> made from all possible combinations of <tt>-2<\/tt>, <tt>+2<\/tt> and <tt>0<\/tt>.  A typical <tt>v<\/tt> is<\/p><pre>       [-3 -3 -3; -3 -3 3; -3 3 -3; -3 3 3\r\n         3 -3 -3;  3 -3 3;  3 3 -3;  3 3 3]\/9  +  [0 -2  2]<\/pre><p>The vectors <tt>[x y z]<\/tt> are coordinates of <i>cube centers<\/i>. The addition of a vector to an array is a case of MATLAB's <i>singleton expansion<\/i>.  The translated <tt>v<\/tt> may not be nearby, but it is <i>somewhere<\/i> in the sponge.  And <i>all<\/i> of the cubes in the sponge are reached by the recursion.<\/p><p>Now a key point.  The function <tt>nnz<\/tt> in the innermost loop counts the number of nonzero components in a vector. The cubes that would be obtained by translation with <tt>nnz([x y z])<\/tt> equal to <tt>0<\/tt> or <tt>1<\/tt> are skipped because they are precisely the cubes that provide the holes in the fractal.<\/p><pre class=\"language-matlab\"><span class=\"keyword\">function<\/span> sponge(v,level,lit)\r\n  <span class=\"keyword\">if<\/span> level &gt; 0\r\n      v = v\/3;\r\n      <span class=\"keyword\">for<\/span> x = [-2 0 2]\r\n          <span class=\"keyword\">for<\/span> y = [-2 0 2]\r\n              <span class=\"keyword\">for<\/span> z = [-2 0 2]\r\n                  <span class=\"keyword\">if<\/span> nnz([x y z]) &gt; 1\r\n                      sponge(v+[x y z],level-1,lit)\r\n                  <span class=\"keyword\">end<\/span>\r\n              <span class=\"keyword\">end<\/span>\r\n          <span class=\"keyword\">end<\/span>\r\n      <span class=\"keyword\">end<\/span>\r\n  <span class=\"keyword\">else<\/span>\r\n      cube(v,lit)\r\n  <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><h4><tt>cube<\/tt><a name=\"c9ada87e-ef74-4474-a4eb-081c12c2b356\"><\/a><\/h4><p>This function uses <tt>patch<\/tt> to plot the six faces of a gold cube. If lighting is required some specular reflectance parameters are set by <tt>material<\/tt>.<\/p><pre class=\"language-matlab\"><span class=\"keyword\">function<\/span> cube(v,lit)\r\n    f = [ 1 5 7 3\r\n          3 7 8 4\r\n          1 3 4 2\r\n          2 4 8 6\r\n          1 2 6 5\r\n          5 6 8 7];\r\n    gold = [1 .85 .60];\r\n    p = patch(Vertices = v, <span class=\"keyword\">...<\/span>\r\n            Faces = f, <span class=\"keyword\">...<\/span>\r\n            FaceColor = gold, <span class=\"keyword\">...<\/span>\r\n            LineWidth = 0.5);\r\n    <span class=\"keyword\">if<\/span> lit\r\n        golden = [0.7,0.5,0.3,1.0,0.2];\r\n        material(p,golden)\r\n    <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><h4><tt>init_fig<\/tt><a name=\"ec0270ea-6840-4e49-b600-33a47bb84c4c\"><\/a><\/h4><p>Initializes the figure, the axis and, if desired, a light pointed at the cube from the viewing position. The name <tt>windowbuttonmotionfcn<\/tt> is the longest identifier in MATLAB and a very handy function.  We need one of these here so the light follows along when we rotate a sponge.<\/p><pre class=\"language-matlab\"><span class=\"keyword\">function<\/span> init_fig(lit)\r\n    axis(4*[-1 1 -1 1 -1 1])\r\n    axis <span class=\"string\">equal<\/span> <span class=\"string\">off<\/span> <span class=\"string\">vis3d<\/span>\r\n    rotate3d <span class=\"string\">on<\/span>\r\n    view(60,15)\r\n    <span class=\"keyword\">if<\/span> lit\r\n        camlight(-45,10);\r\n        set(gcf,<span class=\"string\">'windowbuttonmotionfcn'<\/span>,@wbmf);\r\n    <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><h4><tt>wbmf<\/tt><a name=\"53650df7-81e3-43b1-ba02-08171bde54e8\"><\/a><\/h4><pre class=\"language-matlab\"><span class=\"keyword\">function<\/span> wbmf(~,~)\r\n    a = gca;\r\n    l = findobj(a,<span class=\"string\">'type'<\/span>,<span class=\"string\">'light'<\/span>);\r\n    camlight(l,-45,10);\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><h4>Software<a name=\"3138c9d6-748e-43d4-a279-2943d1e1b839\"><\/a><\/h4><p>My code is available <a href=\"https:\/\/blogs.mathworks.com\/cleve\/files\/menger.m\">here<\/a>.<\/p><h4>Learn more<a name=\"fbfa6b1d-3e8f-4a8c-bd02-11d249bf4f3f\"><\/a><\/h4><p>The Web has lots more about the Menger sponge. People have built ones that you can walk through. People have printed them with 3D printers. Google \"Menger sponge images\" and click on \"see all\".<\/p><p>Wikipedia has a good article. <a href=\"https:\/\/en.wikipedia.org\/wiki\/Menger_sponge\">https:\/\/en.wikipedia.org\/wiki\/Menger_sponge<\/a>.<\/p><p>I particularly enjoyed this video. <a href=\"https:\/\/www.youtube.com\/watch?v=fWsmq9E4YC0\">https:\/\/www.youtube.com\/watch?v=fWsmq9E4YC0<\/a>.<\/p><p>The <i>New York Times<\/i> even has an article. <a href=\"https:\/\/www.nytimes.com\/2011\/06\/28\/science\/28math-menger.html\">https:\/\/www.nytimes.com\/2011\/06\/28\/science\/28math-menger.html<\/a>.<\/p><h4>Thanks<a name=\"fef02937-e0ea-4374-a130-63bab944dce7\"><\/a><\/h4><p>Thanks to Ed Angel for introducing me to Menger's creation and to Bob Blaine for some much needed help with graphics.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_745278049128409989950b52efaa0984() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='745278049128409989950b52efaa0984 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 745278049128409989950b52efaa0984';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2021 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_745278049128409989950b52efaa0984()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2021a<br><\/p><\/div><!--\r\n745278049128409989950b52efaa0984 ##### SOURCE BEGIN #####\r\n%% The Menger Sponge Fractal\r\n% The Menger sponge is a popular fractal that generalizes\r\n% Cantor sets and Sierpinski triangles.\r\n% Its fractal dimension is between two and three.\r\n\r\n%% Karl Menger\r\n% <https:\/\/en.wikipedia.org\/wiki\/Karl_Menger\r\n% Karl Menger> (1902-1985) was a 20th-century Austrian-American\r\n% mathematician.  Most of his career was at the\r\n% Illinois Institute of Technology in Chicago.  He made contributions\r\n% to geometry and game theory.  But he is best known for his\r\n% cube-like fractal known as a \"sponge\".\r\n\r\n%% The Sponge\r\n% Start with a big solid cube.  This is level zero.  \r\n%\r\n% <<small_sponge00.png>>\r\n\r\n%%\r\n% Trisect the big cube into 3x3x3 = 27 smaller cubes, like\r\n% a Rubik's cube without the labels.  Remove\r\n% the center cube from each of the six faces and the cube at the\r\n% very center.  That leaves these 27 - 7 = 20 smaller cubes at level one.\r\n%\r\n% <<small_sponge01.png>>\r\n\r\n%%\r\n% Repeat the process on each of these 20 cubes to generate 20x20 = 400\r\n% even smaller cubes at level two.\r\n%\r\n% <<small_sponge02.png>>\r\n\r\n%%\r\n% Once more.  This is level three with 800 tiny cubes and lots of holes.\r\n%\r\n% <<small_sponge03.png>>\r\n%\r\n\r\n%% What about the next level?\r\n% With the resolution available on our computer screens, or on a printed\r\n% page, there is little to be gained by  going beyond level three.\r\n% Each cube occupies only a few pixels and the level four cubes\r\n% would be 20 times smaller.\r\n%\r\n% And there are 20 times as many of  them.  That's 160,000 subpixel sized\r\n% cubes.\r\n% Even though I wasn't going to be able to view it, I did complete one\r\n% computation at level four.  It requiries more main memory than the \r\n% 32 gigabytes of RAM that I have on my laptop.  It had to use virtual\r\n% storage and ran for almost 15 minutes.\r\n\r\n%% Two- or three-dimensional?\r\n% The solid volume is reduced by a factor of 20\/27 at each level.\r\n% So if you theoretically keep going past level three or four,\r\n% the volume approaches zero.\r\n% On the other hand, the surface area becomes infinite.\r\n% The result is a fractal that\r\n% is somewhere between two- and three-dimensional.\r\n% In 1918, Felix Hausdorff introduced _fractal dimension_.\r\n% It turns out that the Menger sponge has Hausdorff dimension\r\n% log(20)\/log(3), which is about 2.727.\r\n\r\n%% Light on the subject.\r\n% So far, we've been working in the dark.  Let's shed some light on\r\n% the subject.  The big cube we started with is actually (a simulation\r\n% of) solid gold.\r\n%\r\n% <<small_sponge10.png>>\r\n\r\n%%\r\n% The light strikes various surfaces at different angles to produce\r\n% different shades of gold.  We can now easily see the holes.\r\n%\r\n% <<small_sponge11.png>>\r\n\r\n%%\r\n% At level two we have carved out almost half of the gold.\r\n%\r\n% <<small_sponge12.png>>\r\n\r\n%%\r\n% With the light and shading, level three takes about five seconds to\r\n% compute and plot.  It is somewhat darker than the other plots because\r\n% the cubes edges are beginning to dominate.\r\n%\r\n% <<small_sponge13.png>>\r\n%\r\n\r\n%% Tilt\r\n% If you tilt the sponge very slightly, you can see that the holes are\r\n% channels passing all the way through.\r\n%\r\n% <<small_tilt.png>>\r\n\r\n%% Animation\r\n% I try to have animated .gifs in all of my blog posts.\r\n%\r\n% <<sponges.gif>>\r\n\r\n%% |menger|\r\n% Here is my code.  The function |menger| gets things started.  There are\r\n% two input parameters.  The first specifies the desired level of\r\n% refinement.  A single solid cube is |level| = 0.  Increasing\r\n% |level| by one multiplies the number of cubes, and consequently\r\n% both the execution time and the memory required, by a factor of 20.\r\n% Any |level| greater than 3 is impractical.\r\n%\r\n% The second input parameter is true or false.  True turns on a\r\n% |camlight| so you can see more detail.  With false there is no\r\n% lighting.  Lighting takes more time, especially if you expect to\r\n% manipulate the sponge after it has been computed.\r\n%\r\n% The 8-by-3 array |V| provides the vertices of a cube of half-width 3.\r\n% Starting with this width means that many of the subsequent computations\r\n% are done with no roundoff error.  This is important when the size\r\n% of the cubes approaches the graphics resolution.\r\n%\r\n% \r\n%   function menger(level,lit)\r\n%       % Fractal cube, the Menger sponge.\r\n%       % menger(level) generates 20^level cubes.\r\n%       % menger(level,true) is illuminated. \r\n%       % menger(level,false) is not illuminated, so it is faster.\r\n%      \r\n%       V = [-3 -3 -3; -3 -3 3; -3 3 -3; -3 3 3;\r\n%             3 -3 -3;  3 -3 3;  3 3 -3;  3 3 3]; \r\n%       init_fig(lit)\r\n%       sponge(V,level)\r\n%   end\r\n%     \r\n\r\n%% |sponge|\r\n% This is where all the action takes place.\r\n% The function |sponge| is recursive.  It calls itself repeatedly,\r\n% passing arrays |v| representing the vertices of small cubes.\r\n% The |v| arrays are obtained from the original |V|\r\n% by scaling with inverse powers of 3 and translating with\r\n% vectors |[x y z]| made from all possible combinations\r\n% of |-2|, |+2| and |0|.  A typical |v| is\r\n%\r\n%         [-3 -3 -3; -3 -3 3; -3 3 -3; -3 3 3\r\n%           3 -3 -3;  3 -3 3;  3 3 -3;  3 3 3]\/9  +  [0 -2  2]\r\n%\r\n% The vectors |[x y z]| are coordinates of _cube centers_.\r\n% The addition of a vector to an array is a case of MATLAB's\r\n% _singleton expansion_.  The translated |v| may not be nearby, but\r\n% it is _somewhere_ in the sponge.  And _all_ of the cubes in the sponge\r\n% are reached by the recursion.\r\n%\r\n% Now a key point.  The function |nnz| in the innermost loop\r\n% counts the number of nonzero components in a vector.\r\n% The cubes that would be obtained by translation with |nnz([x y z])|\r\n% equal to |0| or |1| are skipped because they are precisely the cubes\r\n% that provide the holes in the fractal.\r\n%\r\n%   function sponge(v,level,lit)\r\n%     if level > 0\r\n%         v = v\/3;\r\n%         for x = [-2 0 2]\r\n%             for y = [-2 0 2]\r\n%                 for z = [-2 0 2]\r\n%                     if nnz([x y z]) > 1\r\n%                         sponge(v+[x y z],level-1,lit)\r\n%                     end \r\n%                 end\r\n%             end\r\n%         end\r\n%     else\r\n%         cube(v,lit)\r\n%     end\r\n%   end\r\n\r\n%% |cube|\r\n% This function uses |patch| to plot the six faces of a gold cube.\r\n% If lighting is required some specular reflectance parameters are\r\n% set by |material|.\r\n% \r\n%   function cube(v,lit)\r\n%       f = [ 1 5 7 3\r\n%             3 7 8 4\r\n%             1 3 4 2\r\n%             2 4 8 6\r\n%             1 2 6 5\r\n%             5 6 8 7];\r\n%       gold = [1 .85 .60];\r\n%       p = patch(Vertices = v, ...\r\n%               Faces = f, ...\r\n%               FaceColor = gold, ...\r\n%               LineWidth = 0.5);\r\n%       if lit\r\n%           golden = [0.7,0.5,0.3,1.0,0.2];\r\n%           material(p,golden)\r\n%       end   \r\n%   end\r\n\r\n%% |init_fig|\r\n% Initializes the figure, the axis and, if desired, a light pointed\r\n% at the cube from the viewing position.\r\n% The name |windowbuttonmotionfcn| is the longest identifier in MATLAB\r\n% and a very handy function.  We need one of these here so the light\r\n% follows along when we rotate a sponge.\r\n% \r\n%   function init_fig(lit) \r\n%       axis(4*[-1 1 -1 1 -1 1])\r\n%       axis equal off vis3d\r\n%       rotate3d on\r\n%       view(60,15) \r\n%       if lit\r\n%           camlight(-45,10);\r\n%           set(gcf,'windowbuttonmotionfcn',@wbmf);\r\n%       end\r\n%   end\r\n\r\n%% |wbmf|\r\n%\r\n%   function wbmf(~,~)\r\n%       a = gca;\r\n%       l = findobj(a,'type','light');\r\n%       camlight(l,-45,10);\r\n%   end  \r\n%\r\n\r\n%% Software\r\n% My code is available <https:\/\/blogs.mathworks.com\/cleve\/files\/menger.m\r\n% here>.\r\n\r\n%% Learn more\r\n% The Web has lots more about the Menger sponge.\r\n% People have built ones that you can walk through.\r\n% People have printed them with 3D printers.\r\n% Google \"Menger sponge images\" and click on \"see all\".\r\n%\r\n% Wikipedia has a good article.\r\n% <https:\/\/en.wikipedia.org\/wiki\/Menger_sponge>.\r\n%\r\n% I particularly enjoyed this video.\r\n% <https:\/\/www.youtube.com\/watch?v=fWsmq9E4YC0>.\r\n%\r\n% The _New York Times_ even has an article.\r\n% <https:\/\/www.nytimes.com\/2011\/06\/28\/science\/28math-menger.html>.\r\n\r\n%% Thanks\r\n% Thanks to Ed Angel for introducing me to Menger's creation\r\n% and to Bob Blaine for some much needed help with graphics.\r\n##### SOURCE END ##### 745278049128409989950b52efaa0984\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/small_sponge00.png\" onError=\"this.style.display ='none';\" \/><\/div><!--introduction--><p>The Menger sponge is a popular fractal that generalizes Cantor sets and Sierpinski triangles. Its fractal dimension is between two and three.... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/cleve\/2021\/12\/06\/the-menger-sponge-fractal\/\">read more >><\/a><\/p>","protected":false},"author":78,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[32,18,5,4,8,37],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts\/7891"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/users\/78"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/comments?post=7891"}],"version-history":[{"count":6,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts\/7891\/revisions"}],"predecessor-version":[{"id":7969,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts\/7891\/revisions\/7969"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/media?parent=7891"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/categories?post=7891"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/tags?post=7891"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}