Geometry
The procedures that measure a vector 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). normalized_checked, the accurate products, the measures and the point location are free procedures only, without a method. All are elemental, except polygon_vector_area, barycentric_triangle and barycentric_tetrahedron, which are pure: the first takes an array of vertices, the other two return an array of coordinates. In the formulas, self) or the point p, and pt1, pt2, ...; the results are of the kind of the vectors.
Lengths and directions
| Call | Result |
|---|---|
v%normL2() | |
v%sq_norm() | |
v%normalized() | |
call v%normalize | v becomes |
call normalized_checked(v, u, ok [, min_norm]) | u = ok true when min_norm; otherwise ok false and u the zero vector |
When tiny (the smallest positive normal number of the kind), normalize and normalized divide by 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.
normalized_checked reports the degenerate case instead. It is a subroutine: u is a type(vector), ok a logical, both intent(out). min_norm (a real of the kind of the vector) defaults to tiny, the threshold of normalize; pass a larger one when a short vector has no reliable direction. When ok is false u is the zero vector, which makes an unchecked use obviously wrong rather than plausible.
Accurate products
| Call | Result |
|---|---|
crossproduct_accurate(a, b) | |
dotproduct_accurate(a, b) |
.cross. rounds both products of a component, crossproduct_accurate computes each component by Kahan's algorithm with a fused multiply-add, dotproduct_accurate by Dot2 (Ogita, Rump and Oishi). On 2000 nearly parallel pairs in double precision, checked against quadruple precision, the error of crossproduct_accurate stayed below .cross. reached
Angle
v%angle(w) is the angle between the two vectors in radians, in
accurate for nearly parallel and nearly opposite vectors, unlike
Face normals
3.----.2 3.----------.2
\ | | |
\ | | |
\ | | |
\| | |
.1 4.----------.1
face_normal3 face_normal4| Call | Result |
|---|---|
face_normal3(pt1=, pt2=, pt3=) | |
face_normal4(pt1=, pt2=, pt3=, pt4=) | |
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| Call | Result |
|---|---|
p%distance_to_line(pt1=, pt2=) | |
p%distance_to_plane(pt1=, pt2=, pt3=) | |
p%distance_vectorial_to_plane(pt1=, pt2=, pt3=) | p |
p%projection_onto_plane(pt1=, pt2=, pt3=) | p |
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.
Measures
| Call | Result |
|---|---|
triangle_area(pt1, pt2, pt3) | |
tetrahedron_volume(pt1, pt2, pt3, pt4) | |
polygon_vector_area(pts) |
The volume is positive when pt4 lies on the side where
Point location
| Call | Result |
|---|---|
barycentric_triangle(p, pt1, pt2, pt3) | real array of 3: the barycentric coordinates of p (of its projection onto the plane) |
barycentric_tetrahedron(p, pt1, pt2, pt3, pt4) | real array of 4: the barycentric coordinates of p |
call closest_point_triangle(p, a, b, c, q, feature) | q (type(vector)), the point of the triangle closest to p, and feature (integer), the feature it lies on |
The coordinates feature is 1, 2, 3 for the vertices a, b, c, 4, 5, 6 for the edges ab, bc, ca, 7 for the face. For the signed distance of a point from a closed triangulated surface, take the closest point over the triangles and sign
Collinear and concyclic points
| Call | True when |
|---|---|
p%is_collinear(pt1=, pt2=) | p%distance_to_line(pt1=, pt2=) tolerance |
p%is_concyclic(pt1=, pt2=, pt3=) | 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.