{"id":1073,"date":"2016-08-09T11:07:00","date_gmt":"2016-08-09T11:07:00","guid":{"rendered":"https:\/\/block.arch.ethz.ch\/blog\/?p=1073"},"modified":"2016-08-09T11:07:15","modified_gmt":"2016-08-09T11:07:15","slug":"computational-geometry-in-python","status":"publish","type":"post","link":"https:\/\/block.arch.ethz.ch\/blog\/2016\/08\/computational-geometry-in-python\/","title":{"rendered":"Computational Geometry in Python"},"content":{"rendered":"<p>This post provides a list of Python functions that are very common in structural design calculations. They are not specifically optimised in any way. Therefore, you may end up using entirely different implementations in a real project. The list is a work in progress. I will try to add more examples soon&#8230;<\/p>\n<p><!--more--><\/p>\n<p>Before continuing, note that there are several ways to do the same (or similar) things in Python. Some are faster than others, and, depending on who you ask, some are more &#8220;pythonic&#8221; than others. To illustrate this, but most certainly without making any claims about which one is &#8220;better&#8221; or faster, I include here 10 different ways to compute the length of a vector. There are probably quite a few more, but some of the variations are already a bit contrived, so I will leave it at that :).<\/p>\n<pre class=\"brush:py;toolbar:false;gutter:false\">\r\nfrom operator import add, pow \r\n\r\nl = (v[0] ** v[0] + v[1] ** v[1] + v[2] ** v[2]) **0.5\r\nl = (v[0] **2 + v[1] **2 + v[2] **2) **0.5\r\nl = sum([v[i]**2 for i in range(3)]) **0.5\r\nl = sum(v[i]**2 for i in range(3)) **0.5\r\nl = sum(x * x for x in v) **0.5\r\nl = sum(x **2 for x in v) **0.5\r\nl = sum(map(pow, v, [2, 2, 2])) **0.5\r\nl = sum(map(pow, v, [2] * 3)) **0.5\r\nl = reduce(add, map(pow, v, [2, 2, 2])) **0.5\r\nl = reduce(lambda x, y: x + y, [x **2 for x in v]) **0.5\r\n\r\n# v = [1., 1., 1.]\r\n# 1.7320508075688772\r\n<\/pre>\n<p>Note that I have used <code>**0.5<\/code> to take the square root. Therefore, for each variation, there is at least one other version using the <code>math.sqrt<\/code> function instead&#8230; For a speed comparison between the two, and many opinions about which one is more &#8220;pythonic&#8221;, see <a href=\"http:\/\/stackoverflow.com\/questions\/327002\/which-is-faster-in-python-x-5-or-math-sqrtx\" target=\"_blank\">this StackOverflow post<\/a>.<\/p>\n<p>And then now, without fruther ado, the list of geometry functions&#8230;<\/p>\n<h3>Length<\/h3>\n<pre class=\"brush:py;toolbar:false;gutter:false\">\r\ndef length(v):\r\n    return sqrt(sum(axis * axis for axis in v))\r\n<\/pre>\n<h3>Distance<\/h3>\n<pre class=\"brush:py;toolbar:false;gutter:false\">\r\ndef distance(a, b):\r\n    return sqrt(sum((a[i] - b[i]) ** 2 for i in range(3)))\r\n<\/pre>\n<h3>Dot product<\/h3>\n<pre class=\"brush:py;toolbar:false;gutter:false\">\r\ndef dot(u, v):\r\n    return sum(u[i] * v[i] for i in range(3))\r\n<\/pre>\n<h3>Cross product<\/h3>\n<pre class=\"brush:py;toolbar:false;gutter:false\">\r\ndef cross(u, v):\r\n    return [u[1] * v[2] - u[2] * v[1], \r\n            u[2] * v[0] - u[0] * v[2],\r\n            u[0] * v[1] - u[1] * v[0]]\r\n<\/pre>\n<h3>Centroid<\/h3>\n<pre class=\"brush:py;toolbar:false;gutter:false\">\r\ndef centroid(points):\r\n    p = len(points)\r\n    return [sum(axis) \/ p for axis in zip(*points)]\r\n<\/pre>\n<p>Note that in the context of vector computations, you could think of the combination of the &#8220;unpacking operator (*)&#8221; and the zip function as taking the transpose of a list of vectors.<\/p>\n<pre class=\"brush:py;toolbar:false;gutter:false\">\r\n>>> points = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]\r\n>>> zip(*points)\r\n[[1, 1, 1], [2, 2, 2], [3, 3, 3]]\r\n<\/pre>\n<h3>Area (triangle)<\/h3>\n<pre class=\"brush:py;toolbar:false;gutter:false\">\r\nab = [b[i] - a[i] for i in range(3)]\r\nac = [c[i] - a[i] for i in range(3)]\r\n\r\narea = 0.5 * length(cross(ab, ac))\r\n<\/pre>\n<h3>Area (polygon)<\/h3>\n<pre class=\"brush:py;toolbar:false;gutter:false\">\r\narea = 0\r\nc = centroid(polygon)\r\n\r\nfor i in range(-1, len(polygon) - 1):\r\n    a  = polygon[i]\r\n    b  = polygon[i + 1]\r\n    ab = [b[j] - a[j] for j in range(3)] \r\n    ac = [c[j] - a[j] for j in range(3)] \r\n    area += 0.5 * length(cross(ab, ac))\r\n<\/pre>\n<h3>Volume<\/h3>\n<p>&#8230;<\/p>\n<h3>Center of mass (polygon)<\/h3>\n<p>&#8230;<\/p>\n<h3>Center of mass (polyhedron)<\/h3>\n<p>&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post provides a list of Python functions that are very common in structural design calculations. They are not specifically optimised in any way. Therefore, you may end up using entirely different implementations in a real project. The list is a work in progress. I will try to add more examples soon&#8230;<\/p>\n","protected":false},"author":11,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"class_list":["post-1073","post","type-post","status-publish","format-standard","hentry","category-code"],"_links":{"self":[{"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/posts\/1073","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/comments?post=1073"}],"version-history":[{"count":19,"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/posts\/1073\/revisions"}],"predecessor-version":[{"id":1103,"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/posts\/1073\/revisions\/1103"}],"wp:attachment":[{"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/media?parent=1073"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/categories?post=1073"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/block.arch.ethz.ch\/blog\/wp-json\/wp\/v2\/tags?post=1073"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}