{"id":2154,"date":"2008-03-14T09:44:44","date_gmt":"2008-03-14T14:44:44","guid":{"rendered":"https:\/\/blogs.mathworks.com\/pick\/2008\/03\/14\/fitting-a-circle-easily\/"},"modified":"2016-05-10T15:15:52","modified_gmt":"2016-05-10T19:15:52","slug":"fitting-a-circle-easily","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/pick\/2008\/03\/14\/fitting-a-circle-easily\/","title":{"rendered":"Fitting a Circle, easily."},"content":{"rendered":"<div class=\"content\">\r\n\r\n<i>You may have noticed some recent changes in the format of this blog. Here\u2019s what to expect on a regular basis \u2013 two topics\r\nper week.<\/i>\r\n\r\n&nbsp;\r\n<div>\r\n<ul>\r\n\t<li><i>On Tuesdays Doug will provide MATLAB tutorials.<\/i><\/li>\r\n\t<li><i>On Fridays guest bloggers Jiro, Brett and Bob will highlight File Exchange submissions.<\/i><\/li>\r\n<\/ul>\r\n<\/div>\r\nA file need not be long to be useful. Brett's pick this week, Izhak Bucher's <a title=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/loadFile.do?objectId=5557&amp;objectType=FILE (link no longer works)\">Circle Fit<\/a>, is only 5 lines long, excluding comments. But I really like Izhak's entry, and have had many opportunities to use it in\r\nthe several years since I downloaded it. Somehow, the requirement of fitting a circle to some points seems to occur with puzzling\r\nfrequency in my work. Izhak's CIRCFIT makes it easy, and is quite robust in most cases.\r\n\r\nSo how do you use Izhak's function? Consider these noisy data created for illustrative purposes:\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">R = 10; x_c = 5; y_c = 8;\r\nthetas = 0:pi\/64:pi;\r\nxs = x_c + R*cos(thetas);\r\nys = y_c + R*sin(thetas);\r\n\r\n<span style=\"color: #228b22;\">% Now add some random noise to make the problem a bit more challenging:<\/span>\r\nmult = 0.5;\r\nxs = xs+mult*randn(size(xs));\r\nys = ys+mult*randn(size(ys));<\/pre>\r\nPlot the points...\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">figure\r\nplot(xs,ys,<span style=\"color: #a020f0;\">'b.'<\/span>)\r\naxis <span style=\"color: #a020f0;\">equal<\/span><\/pre>\r\n<img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/pick\/circfit_potw_01.png\" alt=\"\" hspace=\"5\" vspace=\"5\" \/>\r\n\r\n...and then calculate and display the best-fit circle\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">[xfit,yfit,Rfit] = circfit(xs,ys);\r\nfigure\r\nplot(xs,ys,<span style=\"color: #a020f0;\">'b.'<\/span>)\r\nhold <span style=\"color: #a020f0;\">on<\/span>\r\nrectangle(<span style=\"color: #a020f0;\">'position'<\/span>,[xfit-Rfit,yfit-Rfit,Rfit*2,Rfit*2],<span style=\"color: #0000ff;\">...<\/span>\r\n    <span style=\"color: #a020f0;\">'curvature'<\/span>,[1,1],<span style=\"color: #a020f0;\">'linestyle'<\/span>,<span style=\"color: #a020f0;\">'-'<\/span>,<span style=\"color: #a020f0;\">'edgecolor'<\/span>,<span style=\"color: #a020f0;\">'r'<\/span>);\r\ntitle(sprintf(<span style=\"color: #a020f0;\">'Best fit: R = %0.1f; Ctr = (%0.1f,%0.1f)'<\/span>,<span style=\"color: #0000ff;\">...<\/span>\r\n    Rfit,xfit,yfit));\r\nplot(xfit,yfit,<span style=\"color: #a020f0;\">'g.'<\/span>)\r\nxlim([xfit-Rfit-2,xfit+Rfit+2])\r\nylim([yfit-Rfit-2,yfit+Rfit+2])\r\naxis <span style=\"color: #a020f0;\">equal<\/span><\/pre>\r\n<img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/pick\/circfit_potw_02.png\" alt=\"\" hspace=\"5\" vspace=\"5\" \/>\r\n\r\nBy the way, if it seems odd to you to use a RECTANGLE command to plot a circle, stay tuned for next week's Pick of the Week!\r\n\r\nWhat other data-fitting problems do you commonly come up against, and how do you solve them?\r\n\r\n<script>\/\/ <![CDATA[\r\nfunction grabCode_b5df0be6964241e49925ffed20970129() {\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='b5df0be6964241e49925ffed20970129 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' b5df0be6964241e49925ffed20970129';\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        author = 'Brett Shoelson';\r\n        copyright = 'Copyright 2008 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('\r\n\r\n\r\n\r\n<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\r\n\r\n\r\n\r\n\r\n\\n');\r\n      \r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }\r\n\/\/ ]]><\/script>\r\n<p style=\"text-align: right; font-size: xx-small; font-weight: lighter; font-style: italic; color: gray;\"><a><span style=\"font-size: x-small; font-style: italic;\">Get\r\nthe MATLAB code\r\n<noscript>(requires JavaScript)<\/noscript><\/span><\/a><\/p>\r\nPublished with MATLAB\u00ae 7.6\r\n\r\n<\/div>\r\n<!--\r\nb5df0be6964241e49925ffed20970129 ##### SOURCE BEGIN #####\r\n%%\r\n% _You may have noticed some recent changes in the format of this blog. Here\u00e2\u20ac\u2122s\r\n% what to expect on a regular basis \u00e2\u20ac\u201c two topics per week._\r\n%%\r\n% * _On Tuesdays Doug will provide MATLAB tutorials._\r\n% * _On Fridays guest bloggers Jiro, Brett and Bob will highlight File\r\n% Exchange submissions._\r\n\r\n%%\r\n% A file need not be long to be useful. <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/loadAuthor.do?objectId=1093599&objectType=author Brett>'s pick this week, <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/loadAuthor.do?objectId=1093629&objectType=author Izhak Bucher>'s <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/loadFile.do?objectId=5557&objectType=FILE Circle Fit>, is only 5 lines long, excluding comments. But I really like Izhak's entry, and have had many opportunities to use it in the several years since I downloaded it.\r\n% Somehow, the requirement of fitting a circle to some points seems to occur with puzzling frequency in my work. Izhak's CIRCFIT makes it easy, and is quite robust in most cases.\r\n\r\n%%\r\n% So how do you use Izhak's function? Consider these noisy data created for\r\n% illustrative purposes:\r\n\r\nR = 10; x_c = 5; y_c = 8;\r\nthetas = 0:pi\/64:pi;\r\nxs = x_c + R*cos(thetas);\r\nys = y_c + R*sin(thetas);\r\n\r\n% Now add some random noise to make the problem a bit more challenging:\r\nmult = 0.5;\r\nxs = xs+mult*randn(size(xs));\r\nys = ys+mult*randn(size(ys));\r\n\r\n%%\r\n% Plot the points...\r\nfigure\r\nplot(xs,ys,'b.')\r\naxis equal\r\n\r\n%%\r\n% ...and then calculate and display the best-fit circle\r\n[xfit,yfit,Rfit] = circfit(xs,ys);\r\nfigure\r\nplot(xs,ys,'b.')\r\nhold on\r\nrectangle('position',[xfit-Rfit,yfit-Rfit,Rfit*2,Rfit*2],...\r\n'curvature',[1,1],'linestyle','-','edgecolor','r');\r\ntitle(sprintf('Best fit: R = %0.1f; Ctr = (%0.1f,%0.1f)',...\r\nRfit,xfit,yfit));\r\nplot(xfit,yfit,'g.')\r\nxlim([xfit-Rfit-2,xfit+Rfit+2])\r\nylim([yfit-Rfit-2,yfit+Rfit+2])\r\naxis equal\r\n\r\n%%\r\n% By the way, if it seems odd to you to use a RECTANGLE command to plot a\r\n% circle, stay tuned for next week's Pick of the Week!\r\n%%\r\n% What other data-fitting problems do you commonly come up against, and how\r\n% do you solve them?\r\n##### SOURCE END ##### b5df0be6964241e49925ffed20970129\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n\r\nYou may have noticed some recent changes in the format of this blog. Here\u2019s what to expect on a regular basis \u2013 two topics\r\nper week.\r\n\r\n&nbsp;\r\n\r\n\r\n\tOn Tuesdays Doug will provide MATLAB... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/pick\/2008\/03\/14\/fitting-a-circle-easily\/\">read more >><\/a><\/p>","protected":false},"author":34,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/2154"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/users\/34"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/comments?post=2154"}],"version-history":[{"count":2,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/2154\/revisions"}],"predecessor-version":[{"id":7103,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/2154\/revisions\/7103"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/media?parent=2154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/categories?post=2154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/tags?post=2154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}