{"id":414,"date":"2024-12-01T18:08:29","date_gmt":"2024-12-01T18:08:29","guid":{"rendered":"https:\/\/permutationcity.co.uk\/bp\/?p=414"},"modified":"2025-03-13T10:26:31","modified_gmt":"2025-03-13T10:26:31","slug":"area-of-a-triangle","status":"publish","type":"post","link":"https:\/\/permutationcity.co.uk\/bp\/2024\/12\/01\/area-of-a-triangle\/","title":{"rendered":"Area of a triangle"},"content":{"rendered":"\n<p>This is a bit specific but that is the way with some algorithms, or formulas in this case.\nLet&#8217;s say you want to calculate the area of a triangle.\nI&#8217;m not sure why.\nIt could be something in a graphics shader for a fancy effect.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"winging-it\">Winging it<\/h2>\n\n\n\n<p>It&#8217;s been a long time since high school geometry.\nI definitely remember that the area of a right angled triangle is <code>base * height \/ 2<\/code>.\nThat makes sense as it&#8217;s <em>half<\/em> of a rectangle.\nActually that formula works even if it\n<a href=\"https:\/\/en.wikipedia.org\/wiki\/Area_of_a_triangle\">isn&#8217;t a right angle triangle<\/a>.\nAny triangle will do as long as the base is the length of one side and\nthe height is measured relative to that side.<\/p>\n\n\n\n<p>That&#8217;s fine in a maths example when things are aligned to the axes but\nwe dealing arbitrary triangle.\nWe are likely to have three random points.\nWe can calculate the length of any side easily but\nabout the height relative to that?\nActually two points make a line and\nI already have the code to calculate the\n<a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/03\/07\/ai-assistance\/\">distance between a point and a line<\/a>.\nI&#8217;ll assume we have:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">struct Point {\n    double x, y;\n};\n\nstruct Line {\n    Point start, end;\n};\n\ndouble DistanceBetween(Point point, Point other);\ndouble DistanceBetween(Point point, Line line);<\/pre><\/div>\n\n\n\n<p>With that the area is just:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">struct Triangle {\n    std::array&lt;Point, 3&gt; points;\n};\n\nfloat AreaOf(Triangle triangle) {\n    Line line(triangle.points[0], triangle.points[1]);\n    Point point(triangle.points[2]);\n\n    float base = DistanceBetween(line.start, line.end);\n    float height = DistanceBetween(point, line);\n    return 0.5 * base * height;\n}<\/pre><\/div>\n\n\n\n<p>That seems okay for now.\nThere might be some edge cases to worry about such as points overlapping or being in a line.\nIs this a <em>good<\/em> algorithm?\nIf I assume that the function for the distance between a point and a line is a given then it&#8217;s simple.\nLooking through it there are 6 additions \/ subtractions, 7 multiplications, 1 division, 1 square root and 1 branch.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"herons-formula\">Heron&#8217;s formula<\/h2>\n\n\n\n<p>The inspiration for the post is\n<a href=\"https:\/\/en.wikipedia.org\/wiki\/Heron%27s_formula\">Heron&#8217;s formula<\/a>.\nLet&#8217;s say we have a triangle with points <strong>P<\/strong>, <strong>Q<\/strong> and <strong>R<\/strong>.\nWe can call the side lengths <strong>PQ<\/strong>, <strong>QR<\/strong> and <strong>RP<\/strong>.\nAs if by magic:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    auto area = 0.25f * sqrt(\n            ( PQ + QR + RP) *\n            (-PQ + QR + RP) *\n            ( PQ - QR + RP) *\n            ( PQ + QR - RP)\n        );<\/pre><\/div>\n\n\n\n<p>Alternatively we can use the <em>semiperimeter<\/em> which is maths speak for &#8220;half the perimeter&#8221;:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    auto semiperimeter = 0.5f * (PQ + QR + RP);\n    auto area = sqrt(\n             semiperimeter *\n            (semiperimeter - PQ) *\n            (semiperimeter - QR) *\n            (semiperimeter - RP)\n        );<\/pre><\/div>\n\n\n\n<p>So it just takes the perimeter of the triangle and the length of each pair of sides minus the odd one out.\nMixes them all together with a bit of multiplication and a square root.\nIs this a <em>good<\/em> algorithm?\nI have no idea why it works but it apparently does.\nIt takes 6 additions \/ subtractions, 4 multiplications and 1 square root.<\/p>\n\n\n\n<p>I&#8217;ve got a sneaking suspicion that the additions and multiplications might not matter.\nThere are a number of\n<a href=\"https:\/\/en.wikipedia.org\/wiki\/Methods_of_computing_square_roots\">methods for calculating square roots<\/a>\nwith varying levels of complexity.\nBoth algorithms use a square root but\nHeron&#8217;s formula uses it as a last step.\nThat means it would be easy to skip if you can make do with the area squared.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-real-world\">The real world<\/h2>\n\n\n\n<p>Guessing about performance can only go so far. In the end you have to do a real comparison and it&#8217;s <a href=\"https:\/\/quick-bench.com\/q\/zR0S_shz0K36ZeOXw1nVsmO0B9o\">not what I expected<\/a>. The &#8220;off the top of my head&#8221; method is about twice as fast as this magic little formula. I tried to count up the instructions and it seemed as though Heron&#8217;s formula should come out ahead.<\/p>\n\n\n\n<p>First of all I looked at the actual areas being calculated:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;text&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">i:0     4.9413,4.9413\ni:1     9.20024,9.20024\ni:2     0.458383,0.458383\ni:3     1.51573,1.51573\n...\ni:97    5.81562,5.81562\ni:98    0.578402,0.578402\ni:99    19.0903,19.0903<\/pre><\/div>\n\n\n\n<p>I can&#8217;t be certain these are the correct areas but both methods are producing the same areas.<\/p>\n\n\n\n<p>Maybe the problem is that in Heron&#8217;s formula I assumed we <em>already had the side lengths<\/em>. That&#8217;s not true and each of those calculations involves 3 additions \/ subtractions, 2 multiplications and a square root. By pre-calculating the lengths <a href=\"https:\/\/quick-bench.com\/q\/wx_OJZL9fLv0WFoQ2-eq8KGe8lk\">should see a better comparison<\/a>. So Heron&#8217;s formula is faster but only if we have the right data.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"in-the-end\">In the end<\/h2>\n\n\n\n<p>I heard about this clever little formula for calculating the area of a triangle.\nIt <em>looked<\/em> as though that could save some computation.\nThat doesn&#8217;t mean that its actually faster.\nProfiling is everything when measuring performance.<\/p>\n\n\n\n<p>It may seem odd that one week I&#8217;ll tell you that performance tricks aren&#8217;t that important.\nThe next week I&#8217;ll dive into detail about the performance of a particular algorithm.\nIt just happens that I <em>enjoy<\/em> some of the details about algorithms.\nI could sit down for a few days or a week to optimise a bit of code to get it 10% faster.\nHowever I also think that in day to day programming that 10% won&#8217;t matter unless\nit&#8217;s the <em>right piece of code<\/em> that gets optimised.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a bit specific but that is the way with some algorithms, or formulas in this case. Let&#8217;s say you want to calculate the area of a triangle. I&#8217;m not sure why. It could be something in a graphics shader for a fancy effect. Winging it It&#8217;s been a long time since high school [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[1],"tags":[22,40,7],"class_list":["post-414","post","type-post","status-publish","format-standard","hentry","category-general","tag-algorithms","tag-geometry","tag-performance"],"_links":{"self":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/414","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/comments?post=414"}],"version-history":[{"count":5,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/414\/revisions"}],"predecessor-version":[{"id":419,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/414\/revisions\/419"}],"wp:attachment":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/media?parent=414"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/categories?post=414"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/tags?post=414"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}