{"id":201,"date":"2015-03-03T14:30:33","date_gmt":"2015-03-03T19:30:33","guid":{"rendered":"https:\/\/blogs.mathworks.com\/graphics\/?p=201"},"modified":"2015-03-11T10:16:35","modified_gmt":"2015-03-11T14:16:35","slug":"implicit-curves","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/graphics\/2015\/03\/03\/implicit-curves\/","title":{"rendered":"Implicit Curves &#038; Surfaces"},"content":{"rendered":"<div class=\"content\"><h3>Implicit Curves and Surfaces<\/h3><p>In some earlier posts ( <a href=\"https:\/\/blogs.mathworks.com\/graphics\/2014\/12\/04\/tie-a-ribbon-round-it-parametric-curves-part-1\/\">part1<\/a>, <a href=\"https:\/\/blogs.mathworks.com\/graphics\/2014\/12\/16\/down-the-tubes\/\">part2<\/a>) we explored how to draw parametric curves using MATLAB Graphics. Now lets turn our attention to implicit curves.<\/p><p>We know that the implicit equation for the unit circle is the following:<\/p><p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_eq06288373408908796908.png\" alt=\"$$x^2 + y^2 = 1$$\"><\/p><p>We can convert that into a parametric form, and then draw it using the techniques we learned earlier.<\/p><pre class=\"codeinput\">t = linspace(0,2*pi,120);\r\nplot(cos(t),sin(t))\r\naxis <span class=\"string\">equal<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_01.png\" alt=\"\"> <p>But converting from implicit form to parametric form can be pretty complicated, even for a curve as simple as the unit circle. And there are implicit curves which don't have a parametric form. It'd be awfully nice if we could plot it directly without converting it to parametric form.<\/p><p>There is actually an easy way to do this, using the <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/contour.html\">contour function<\/a>. The basic idea is that we create a 2D array from the left hand side of the equation, and then contour it with one contour level which is equal to the right hand side of the equation.<\/p><pre class=\"codeinput\">[x,y] = meshgrid(linspace(-1,1,120));\r\ncontour(x,y,x.^2 + y.^2,<span class=\"string\">'LevelList'<\/span>,1);\r\naxis <span class=\"string\">equal<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_02.png\" alt=\"\"> <p>One problem with this approach is that it only works when the right hand side is a constant. To handle a function like this:<\/p><p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_eq02037246090147964752.png\" alt=\"$$x^4 + y^3 = 2 x y$$\"><\/p><p>We'll have to transform it so that all of the non-constant terms are on the left:<\/p><p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_eq10722542577294860154.png\" alt=\"$$x^4 + y^3 - 2 x y = 0$$\"><\/p><pre class=\"codeinput\">[x,y] = meshgrid(linspace(-2*pi,2*pi,120));\r\ncontour(x,y,x.^4 + y.^3 - 2*x.*y,<span class=\"string\">'LevelList'<\/span>,0);\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_03.png\" alt=\"\"> <p>MATLAB Graphics actually provides a function which will take care of this for you. It's called <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/ezplot.html\">ezplot<\/a>.<\/p><pre class=\"codeinput\">ezplot(<span class=\"string\">'x^4 + y^3 = 2*x*y'<\/span>)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_04.png\" alt=\"\"> <p>If you've ever used ezplot and looked at its return value, you might have noticed that it returns different types of objects for different types of equations. That's because it's doing exactly what I described above. If we call ezplot with a parametric equation, we get a Line object:<\/p><pre class=\"codeinput\">h = ezplot(<span class=\"string\">'cos(t)'<\/span>,<span class=\"string\">'sin(t)'<\/span>)\r\n<\/pre><pre class=\"codeoutput\">\r\nh = \r\n\r\n  Line with properties:\r\n\r\n              Color: [0 0.4470 0.7410]\r\n          LineStyle: '-'\r\n          LineWidth: 0.5000\r\n             Marker: 'none'\r\n         MarkerSize: 6\r\n    MarkerFaceColor: 'none'\r\n              XData: [1x300 double]\r\n              YData: [1x300 double]\r\n              ZData: [1x0 double]\r\n\r\n  Use GET to show all properties\r\n\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_05.png\" alt=\"\"> <p>But if we call it with an implicit equation, we get a Contour object:<\/p><pre class=\"codeinput\">h = ezplot(<span class=\"string\">'x^2 + y^2 = 1'<\/span>,[-1 1])\r\naxis <span class=\"string\">equal<\/span>\r\n<\/pre><pre class=\"codeoutput\">\r\nh = \r\n\r\n  Contour with properties:\r\n\r\n    LineColor: 'flat'\r\n    LineStyle: '-'\r\n    LineWidth: 0.5000\r\n         Fill: 'off'\r\n    LevelList: 0\r\n        XData: [1x250 double]\r\n        YData: [250x1 double]\r\n        ZData: [250x250 double]\r\n\r\n  Use GET to show all properties\r\n\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_06.png\" alt=\"\"> <p>What about implicit equations in 3D? Neither the ezplot function or its companion ezsurf can do this. But now that we know how ezplot works for 2D implicit equations, we can use the same technique. We just need to switch from the contour function to the <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/isosurface.html\">isosurface function<\/a>. The isosurface function does for a 3D array what the contour function does for a 2D array.<\/p><p>For example, <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/answers\/156942-how-to-plot-a-3d-ecuation\">Guillermo asked on MATLAB Answers<\/a> how to draw the following surface.<\/p>\r\n<p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_eq06733364453762509290.png\" alt=\"$$(y-z)^2 + (z-x)^2 + (x-y)^2 = 3 R^2$$\"><\/p><p>Where R is a positive integer.<\/p><p>We can generate a 3D grid of the left hand side using ndgrid.<\/p><pre class=\"codeinput\">[y,x,z] = ndgrid(linspace(-5,5,64));\r\nf = (y-z).^2 + (z-x).^2 + (x-y).^2;\r\n<\/pre><p>Once we have that, we can use the isosurface function to figure out where that function is equal to the right hand side for various values of R.<\/p><pre class=\"codeinput\">cla <span class=\"string\">reset<\/span>\r\nr = 1;\r\nisosurface(x,y,z,f,3*r^2)\r\nr = 2;\r\nisosurface(x,y,z,f,3*r^2)\r\nr = 3;\r\nisosurface(x,y,z,f,3*r^2)\r\nview(3)\r\ncamlight\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_07.png\" alt=\"\"> <p>Here's a slightly more complex implicit surface from this <a href=\"http:\/\/math.stackexchange.com\/questions\/152256\/implicit-equation-for-double-torus-genus-2-orientable-surface\">Stack Exchange post<\/a>.<\/p>\r\n<p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_eq07020818729912238603.png\" alt=\"$$(x(x-1)^2(x-2) + y^2)^2 + z^2 = .01$$\"><\/p>\r\n<pre class=\"codeinput\">[y,x,z] = ndgrid(linspace(-.75,.75,100),linspace(-.1,2.1,100),linspace(-.2,.2,100));\r\nf = (x.*(x-1).^2.*(x-2) + y.^2).^2 + z.^2;\r\ncla\r\nisosurface(x,y,z,f,.01);\r\nview(3);\r\ncamlight\r\naxis <span class=\"string\">equal<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_08.png\" alt=\"\"> <p>But some implicit surfaces are very complex and can be rather tricky to render. One of my favorite challenges are the famous <a href=\"http:\/\/en.wikipedia.org\/wiki\/Barth_surface\">Barth surfaces<\/a>. For example, the equation for the sextic is the following:<\/p><p><img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/implicit_curves_eq03787304027125567937.png\" alt=\"$$4(\\phi^2 x^2 - y^2)(\\phi^2 y^2 - x^2)(\\phi^2 z^2 - x^2) = (1+2 \\phi)(x^2 + y^2 + z^2 - w^2)^2 w^2$$\"><\/p><p>Here's a picture I made of it for w=1.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/graphics\/2015\/barth_sextic.png\" alt=\"\"> <\/p><p>Can you create a better picture of this challenging surface or one of its relatives?<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_54823ac542d14f7e80f1f516144bcd1d() {\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='54823ac542d14f7e80f1f516144bcd1d ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 54823ac542d14f7e80f1f516144bcd1d';\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 2015 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_54823ac542d14f7e80f1f516144bcd1d()\"><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; R2014b<br><\/p><\/div><!--\r\n54823ac542d14f7e80f1f516144bcd1d ##### SOURCE BEGIN #####\r\n%% Implicit Curves and Surfaces\r\n% In some earlier posts (\r\n% <https:\/\/blogs.mathworks.com\/graphics\/2014\/12\/04\/tie-a-ribbon-round-it-parametric-curves-part-1\/ part1>, \r\n% <https:\/\/blogs.mathworks.com\/graphics\/2014\/12\/04\/tie-a-ribbon-round-it-parametric-curves-part-2\/ part2>)  \r\n% we explored how to draw parametric curves using MATLAB Graphics. Now lets \r\n% turn our attention to implicit curves.\r\n%\r\n% We know that the implicit equation for the unit circle is the following:\r\n% \r\n% $$x^2 + y^2 = 1$$\r\n%\r\n% We can convert that into a parametric form, and then draw it using the \r\n% techniques we learned earlier.\r\nt = linspace(0,2*pi,120);\r\nplot(cos(t),sin(t))\r\naxis equal\r\n\r\n%%\r\n% But converting from implicit form to parametric form can be pretty \r\n% complicated, even for a curve as simple as the unit circle. And there are \r\n% implicit curves which don't have a parametric form. It'd be awfully nice \r\n% if we could plot it directly without converting it to parametric form.\r\n%\r\n% There is actually an easy way to do this, using the <https:\/\/www.mathworks.com\/help\/matlab\/ref\/contour.html contour function>. The\r\n% basic idea is that we create a 2D array from the left hand side of the \r\n% equation, and then contour it with one contour level which is equal to\r\n% the right hand side of the equation.\r\n[x,y] = meshgrid(linspace(-1,1,120));\r\ncontour(x,y,x.^2 + y.^2,'LevelList',1);\r\naxis equal\r\n\r\n%%\r\n% One problem with this approach is that it only works when the right\r\n% hand side is a constant. To handle a function like this:\r\n%\r\n% $$x^4 + y^3 = 2 x y$$\r\n%\r\n% We'll have to transform it so that all of the non-constant terms are on\r\n% the left:\r\n%\r\n% $$x^4 + y^3 - 2 x y = 0$$\r\n%\r\n[x,y] = meshgrid(linspace(-2*pi,2*pi,120));\r\ncontour(x,y,x.^4 + y.^3 - 2*x.*y,'LevelList',0);\r\n\r\n%%\r\n% MATLAB Graphics actually provides a function which will take care of this \r\n% for you. It's called <https:\/\/www.mathworks.com\/help\/matlab\/ref\/ezplot.html ezplot>. \r\nezplot('x^4 + y^3 = 2*x*y')\r\n\r\n%%\r\n% If you've ever used ezplot and looked at its return value, you might have\r\n% noticed that it returns different types of objects for different types of\r\n% equations. That's because it's doing exactly what I described above. If\r\n% we call ezplot with a parametric equation, we get a Line object:\r\nh = ezplot('cos(t)','sin(t)')\r\n\r\n%%\r\n% But if we call it with an implicit equation, we get a Contour object:\r\nh = ezplot('x^2 + y^2 = 1',[-1 1])\r\naxis equal\r\n\r\n%%\r\n% What about implicit equations in 3D? Neither the ezplot function or its \r\n% companion ezsurf can do this. But now that we know how ezplot \r\n% works for 2D implicit equations, we can use the same technique. We just \r\n% need to switch from the contour function to the <https:\/\/www.mathworks.com\/help\/matlab\/ref\/isosurface.html isosurface function>. The \r\n% isosurface function does for a 3D array what the contour function does \r\n% for a 2D array.\r\n%\r\n% For example, <https:\/\/www.mathworks.com\/matlabcentral\/answers\/156942-how-to-plot-a-3d-ecuation Guillermo asked on MATLAB Answers> how to draw the \r\n% following surface.\r\n%\r\n% $$(y-z)^2 + (z-x)^2 + (x-y)^2 = 3 R^2$$\r\n%\r\n% Where R is a positive integer.\r\n%\r\n% We can generate a 3D grid of the left hand side using ndgrid.\r\n[y,x,z] = ndgrid(linspace(-5,5,64));\r\nf = (y-z).^2 + (z-x).^2 + (x-y).^2;\r\n\r\n%%\r\n% Once we have that, we can use the isosurface function to figure out where\r\n% that function is equal to the right hand side for various values of R.\r\ncla reset\r\nr = 1;\r\nisosurface(x,y,z,f,3*r^2)\r\nr = 2;\r\nisosurface(x,y,z,f,3*r^2)\r\nr = 3;\r\nisosurface(x,y,z,f,3*r^2)\r\nview(3)\r\ncamlight\r\n\r\n\r\n%%\r\n% Here's a slightly more complex implicit surface from this\r\n% <http:\/\/math.stackexchange.com\/questions\/152256\/implicit-equation-for-double-torus-genus-2-orientable-surface\r\n% Stack Exchange post>.\r\n%\r\n% $$(x(x-1)^2(x-2) + y^2)^2 + z^2 = .01$$\r\n%\r\n[y,x,z] = ndgrid(linspace(-.75,.75,100),linspace(-.1,2.1,100),linspace(-.2,.2,100));\r\nf = (x.*(x-1).^2.*(x-2) + y.^2).^2 + z.^2;\r\ncla\r\nisosurface(x,y,z,f,.01);\r\nview(3);\r\ncamlight\r\naxis equal\r\n\r\n%%\r\n% But some implicit surfaces are very complex and can be rather tricky to render. \r\n% One of my favorite challenges are the famous <http:\/\/en.wikipedia.org\/wiki\/Barth_surface Barth surfaces>. \r\n% For example, the equation for the sextic is the following:\r\n%\r\n% $$4(\\phi^2 x^2 - y^2)(\\phi^2 y^2 - x^2)(\\phi^2 z^2 - x^2) = (1+2 \\phi)(x^2 + y^2 + z^2 - w^2)^2 w^2$$\r\n%\r\n% Here's a picture I made of it for w=1.\r\n%\r\n% <<barth_sextic.png>>\r\n%\r\n% Can you create a better picture of this challenging surface or one of its \r\n% relatives?\r\n\r\n##### SOURCE END ##### 54823ac542d14f7e80f1f516144bcd1d\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img src=\"https:\/\/blogs.mathworks.com\/graphics\/files\/feature_image\/barth_sextic.png\" class=\"img-responsive attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" decoding=\"async\" loading=\"lazy\" \/><\/div><p>Implicit Curves and SurfacesIn some earlier posts ( part1, part2) we explored how to draw parametric curves using MATLAB Graphics. Now lets turn our attention to implicit curves.We know that the... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/graphics\/2015\/03\/03\/implicit-curves\/\">read more >><\/a><\/p>","protected":false},"author":89,"featured_media":206,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/posts\/201"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/users\/89"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/comments?post=201"}],"version-history":[{"count":8,"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/posts\/201\/revisions"}],"predecessor-version":[{"id":211,"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/posts\/201\/revisions\/211"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/media\/206"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/media?parent=201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/categories?post=201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/graphics\/wp-json\/wp\/v2\/tags?post=201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}