Computational Geometry in Python
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…
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 “pythonic” than others. To illustrate this, but most certainly without making any claims about which one is “better” 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 :).
01.
from
operator
import
add, pow
02.
03.
l
=
(v[
0
]
*
*
v[
0
]
+
v[
1
]
*
*
v[
1
]
+
v[
2
]
*
*
v[
2
])
*
*
0.5
04.
l
=
(v[
0
]
*
*
2
+
v[
1
]
*
*
2
+
v[
2
]
*
*
2
)
*
*
0.5
05.
l
=
sum([v[i]
*
*
2
for
i
in
range(
3
)])
*
*
0.5
06.
l
=
sum(v[i]
*
*
2
for
i
in
range(
3
))
*
*
0.5
07.
l
=
sum(x
*
x
for
x
in
v)
*
*
0.5
08.
l
=
sum(x
*
*
2
for
x
in
v)
*
*
0.5
09.
l
=
sum(map(pow, v, [
2
,
2
,
2
]))
*
*
0.5
10.
l
=
sum(map(pow, v, [
2
]
*
3
))
*
*
0.5
11.
l
=
reduce(add, map(pow, v, [
2
,
2
,
2
]))
*
*
0.5
12.
l
=
reduce(
lambda
x, y: x
+
y, [x
*
*
2
for
x
in
v])
*
*
0.5
13.
14.
# v = [1., 1., 1.]
15.
# 1.7320508075688772
Note that I have used **0.5
to take the square root. Therefore, for each variation, there is at least one other version using the math.sqrt
function instead… For a speed comparison between the two, and many opinions about which one is more “pythonic”, see this StackOverflow post.
And then now, without fruther ado, the list of geometry functions…
Length
1.
def
length(v):
2.
return
sqrt(sum(axis
*
axis
for
axis
in
v))
Distance
1.
def
distance(a, b):
2.
return
sqrt(sum((a[i]
-
b[i])
*
*
2
for
i
in
range(
3
)))
Dot product
1.
def
dot(u, v):
2.
return
sum(u[i]
*
v[i]
for
i
in
range(
3
))
Cross product
1.
def
cross(u, v):
2.
return
[u[
1
]
*
v[
2
]
-
u[
2
]
*
v[
1
],
3.
u[
2
]
*
v[
0
]
-
u[
0
]
*
v[
2
],
4.
u[
0
]
*
v[
1
]
-
u[
1
]
*
v[
0
]]
Centroid
1.
def
centroid(points):
2.
p
=
len(points)
3.
return
[sum(axis)
/
p
for
axis
in
zip(
*
points)]
Note that in the context of vector computations, you could think of the combination of the “unpacking operator (*)” and the zip function as taking the transpose of a list of vectors.
1.
>>> points
=
[[
1
,
2
,
3
], [
1
,
2
,
3
], [
1
,
2
,
3
]]
2.
>>> zip(
*
points)
3.
[[
1
,
1
,
1
], [
2
,
2
,
2
], [
3
,
3
,
3
]]
Area (triangle)
1.
ab
=
[b[i]
-
a[i]
for
i
in
range(
3
)]
2.
ac
=
[c[i]
-
a[i]
for
i
in
range(
3
)]
3.
4.
area
=
0.5
*
length(cross(ab, ac))
Area (polygon)
01.
area
=
0
02.
c
=
centroid(polygon)
03.
04.
for
i
in
range(
-
1
, len(polygon)
-
1
):
05.
a
=
polygon[i]
06.
b
=
polygon[i
+
1
]
07.
ab
=
[b[j]
-
a[j]
for
j
in
range(
3
)]
08.
ac
=
[c[j]
-
a[j]
for
j
in
range(
3
)]
09.
area
+
=
0.5
*
length(cross(ab, ac))
Volume
…
Center of mass (polygon)
…
Center of mass (polyhedron)
…