Skip to content

Geometry ​

The methods of a vector that measure it or relate it, as a point, to other points. Each method that returns a value is also a free function (see Methods and free functions); all of them are elemental. In the formulas, p is the vector the method is called on (self) and p1,p2,… its arguments pt1, pt2, ...; the results are of the kind of the vectors.

Lengths and directions ​

CallResult
v%normL2()|v|=vx2+vy2+vz2
v%sq_norm()vx2+vy2+vz2
v%normalized()v/|v|, a new vector
call v%normalizev becomes v/|v|

When |v| is below tiny (the smallest positive normal number of the kind), normalize and normalized divide by |v| + tiny instead: the zero vector stays zero, it is not divided by zero. normalize is an elemental subroutine: call p%normalize normalizes a whole array.

Angle ​

v%angle(w) is the angle between the two vectors in radians, in [0,π]:

θ=atan2(|v^×w^|,v^⋅w^)

accurate for nearly parallel and nearly opposite vectors, unlike arccos⁡(v^⋅w^). With a zero vector the angle is 0.

Face normals ​

 3.----.2            3.----------.2
   \   |              |          |
    \  |              |          |
     \ |              |          |
      \|              |          |
       .1            4.----------.1
 face_normal3         face_normal4
CallResult
face_normal3(pt1=, pt2=, pt3=)12(p2−p1)×(p3−p1)
face_normal4(pt1=, pt2=, pt3=, pt4=)12(p3−p1)×(p4−p2)
either, with norm=the same, normalized

The length of the normal is the area of the triangle, and of a flat quadrilateral; for a warped quadrilateral it is the vector area of its four edges. The normal points to the side from which the points are seen counter-clockwise. norm is a character(1): any value, even 'n', asks for the unit normal; leave it out for the area-weighted one. Both are also methods (v%face_normal3(...)), which do not use the vector they are called on.

Distances and projections ​

         . self                   3.----.2
         |                          \   |
         |                           \  *------> . self
 1.-------------.2                    \ |
  distance_to_line                     \|
                                        .1
                                   distance_to_plane
CallResult
p%distance_to_line(pt1=, pt2=)|(p−p1)×(p−p2)|/|p2−p1|
p%distance_to_plane(pt1=, pt2=, pt3=)n^⋅(p−p1), signed
p%distance_vectorial_to_plane(pt1=, pt2=, pt3=)(n^⋅(p−p1))n^, from the plane to p
p%projection_onto_plane(pt1=, pt2=, pt3=)p−(n^⋅(p−p1))n^, the foot of p

n^ is face_normal3(pt1=, pt2=, pt3=, norm='y'): the signed distance is positive on its side, and swapping two of the points changes its sign. The line through pt1 and pt2 is infinite, as is the plane through the three points. The points must define the line or the plane: two coincident points give a distance from the line of NaN; three collinear points give a zero normal, and every distance from their "plane" comes out 0, silently.

Collinear and concyclic points ​

CallTrue when
p%is_collinear(pt1=, pt2=)p%distance_to_line(pt1=, pt2=) ≤ tolerance
p%is_concyclic(pt1=, pt2=, pt3=)|pp1||p2p3|+|p1p2||p3p|−|pp2||p1p3|≤ tiny + tolerance

is_concyclic tests Ptolemy's theorem: the expression is never negative, and is zero exactly when the four points lie on a circle in the order p, pt1, pt2, pt3. tolerance is optional, a real of the kind of the vectors, 0 by default: without it both tests are exact, and a point computed in floating point, on the line or on the circle up to rounding, passes or fails by chance. Pass a tolerance scaled to the geometry: a length for is_collinear, a length squared for is_concyclic.

Released under the GPL v3, BSD 2-Clause, BSD 3-Clause or MIT License.