function dist(a,b) = sqrt(dsq(0) + dsq(1) + dsq(2));
#undef dsq
+#define vsq(i) (v[i]*v[i])
+function vectorlen2d(v) = sqrt(vsq(0) + vsq(1));
+function vectorlen(v) = sqrt(vsq(0) + vsq(1) + vsq(2));
+#undef vsq
+
+function unitvector2d(v) = v / vectorlen2d(v);
+function unitvector(v) = v / vectorlen(v);
+
+function atan2vector(v) = atan2(v[1], v[0]);
+
+// | m[0][0] m[0][1] |
+// | m[1][0] m[1][1] |
+function determinant2(m) = (m[0][0] * m[1][1] - m[0][1] * m[1][0]);
+
+function clockwise2d(v) = [v[1], -v[0]];
+
+// intersection of lines p1..p2 and p3..p4
+function line_intersection_2d(p1,p2,p3,p4) = [
+ // from https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
+ #define XY12 determinant2([p1,p2])
+ #define XY34 determinant2([p3,p4])
+ #define XU12 QU(0,1,2)
+ #define XU34 QU(0,3,4)
+ #define YU12 QU(1,1,2)
+ #define YU34 QU(1,3,4)
+ #define QU(c,i,j) determinant2([[ p##i[c], 1 ], \
+ [ p##j[c], 1 ]])
+ #define DENOM \
+ determinant2([[ XU12, YU12 ], \
+ [ XU34, YU34 ]])
+ //----
+ determinant2([[ XY12, XU12 ],
+ [ XY34, XU34 ]]) / DENOM,
+ determinant2([[ XY12, YU12 ],
+ [ XY34, YU34 ]]) / DENOM,
+ ];
+ #undef XY12
+ #undef XY34
+ #undef XU12
+ #undef XU34
+ #undef YU12
+ #undef YU34
+ #undef QU
+ #undef DENOM
+
+
function circle_point(c, r, alpha) = [ c[0] + r * cos(alpha),
c[1] + r * sin(alpha) ];