MeshLib C++ Docs
Loading...
Searching...
No Matches
Math group

Topics

 2d <-> 3d conversion
 BestFit
 Box
 Constants
 Contour
 High Precision
 Intersection
 Matrix
 Aligning Transform
 Ray Box Intersection
 Triangle intersection
 Tuple Bindings
 Vector

Classes

class  MR::QuadricApprox
struct  MR::DenseBox
class  MR::Histogram
struct  MR::Line< V >
struct  MR::Plane3< T >
struct  MR::PreciseVertCoord
struct  MR::QuadraticForm< V >
struct  MR::Quaternion< T >
struct  MR::SegmPoint< T >
 encodes a point inside a line segment using relative distance in [0,1] More...
struct  MR::Sphere< V >
struct  MR::TriPoint< T >
 encodes a point inside a triangle using barycentric coordinates More...

Functions

template<typename V>
 MR::MR_REQUIRES_IF_SUPPORTED (detail::AffineXf3f::IsValidTemplateArg< V >) struct AffineXf
template<typename T>
AffineXf3< T > MR::lookAt (const Vector3< T > &center, const Vector3< T > &eye, const Vector3< T > &up)
 computes rigid transformation xf
template<typename V>
Box< V > MR::computeBoundingBox (const Vector< V, VertId > &points, VertId firstVert, VertId lastVert, const VertBitSet *region=nullptr, const AffineXf< V > *toWorld=nullptr)
template<typename V>
Box< V > MR::computeBoundingBox (const Vector< V, VertId > &points, const VertBitSet *region=nullptr, const AffineXf< V > *toWorld=nullptr)
template<typename V>
Box< V > MR::computeBoundingBox (const Vector< V, VertId > &points, const VertBitSet &region, const AffineXf< V > *toWorld=nullptr)
AffineXf3d MR::makeRigidXf (const MeshPart &mp, const AffineXf3d &meshXf)
template<typename T>
MR::circumcircleDiameterSq (const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
template<typename T>
MR::circumcircleDiameter (const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
template<typename T>
MR::mincircleDiameterSq (const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
template<typename T>
MR::minTriangleAngleSin (const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
template<typename T>
MR::triangleAspectRatio (const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
template<typename T>
MR::dihedralAngleSin (const Vector3< T > &leftNorm, const Vector3< T > &rightNorm, const Vector3< T > &edgeVec)
template<typename T>
MR::dihedralAngleCos (const Vector3< T > &leftNorm, const Vector3< T > &rightNorm)
template<typename T>
MR::dihedralAngle (const Vector3< T > &leftNorm, const Vector3< T > &rightNorm, const Vector3< T > &edgeVec)
enum class  MR::InSphereResult { MR::InSphereResult::NoSphere , MR::InSphereResult::Outside , MR::InSphereResult::OnSphere , MR::InSphereResult::Inside }
 the result of inSphere predicates More...
InSphereResult MR::inSphere (const Vector3i &a, const Vector3i &b, const Vector3i &c, const Vector3i &d, std::int64_t rSq)
InSphereResult MR::inSphere (const std::array< PreciseVertCoords, 4 > &vs, std::int64_t rSq)
template<typename T>
std::enable_if_t< std::is_floating_point_v< T >, InSphereResultMR::inSphere (const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c, const Vector3< T > &d, T rSq)
 MR::MR_BIND_TEMPLATE (InSphereResult inSphere(const Vector3f &a, const Vector3f &b, const Vector3f &c, const Vector3f &d, float rSq))
 MR::MR_BIND_TEMPLATE (InSphereResult inSphere(const Vector3d &a, const Vector3d &b, const Vector3d &c, const Vector3d &d, double rSq))
using MR::InSphereTesterf = InSphereTester<float>
using MR::InSphereTesterd = InSphereTester<double>
using MR::InSphereTesteri = InSphereTester<int>
bool MR::orient3d (const Vector3i &a, const Vector3i &b, const Vector3i &c)
bool MR::orient3d (const Vector3i &a, const Vector3i &b, const Vector3i &c, const Vector3i &d)
bool MR::orient3d (const std::array< PreciseVertCoords, 4 > &vs)
 first sorts the indices in ascending order, then calls the predicate for sorted points
bool MR::orient3d (const PreciseVertCoords *vs)
TriangleSegmentIntersectResult MR::doTriangleSegmentIntersect (const std::array< PreciseVertCoords, 5 > &vs)
bool MR::segmentIntersectionOrder (const std::array< PreciseVertCoords, 8 > &vs)
ConvertToIntVector MR::getToIntConverter (const Box3d &box)
 creates converter from Vector3f to Vector3i in Box range (int diapason is mapped to box range)
ConvertToFloatVector MR::getToFloatConverter (const Box3d &box)
 creates converter from Vector3i to Vector3f in Box range (int diapason is mapped to box range)
Vector< Vector3i, VertId > MR::computeIntCoords (const ConvertToIntVector &conv, const VertCoords &points, const VertBitSet *valid=nullptr)
VertCoords MR::computeFloatCoords (const ConvertToFloatVector &conv, const Vector< Vector3i, VertId > &intCoords, const VertBitSet *valid=nullptr)
std::optional< Vector3i > MR::findTwoSegmentsIntersection (const Vector3i &ai, const Vector3i &bi, const Vector3i &ci, const Vector3i &di)
Vector3f MR::findTriangleSegmentIntersectionPrecise (const Vector3f &a, const Vector3f &b, const Vector3f &c, const Vector3f &d, const Vector3f &e, CoordinateConverters converters)
template<typename T>
Vector2< T > MR::fromEigen (const Eigen::Matrix< T, 2, 1 > &ev)
template<typename T>
Eigen::Matrix< T, 2, 1 > MR::toEigen (const Vector2< T > &v)
template<typename T>
Eigen::Matrix< T, 2, 2 > MR::toEigen (const SymMatrix2< T > &m)
template<typename T>
Eigen::Matrix< T, 2, 2 > MR::toEigen (const Matrix2< T > &m)
template<typename T>
Matrix2< T > MR::fromEigen (const Eigen::Matrix< T, 2, 2 > &m)
template<typename T>
Vector3< T > MR::fromEigen (const Eigen::Matrix< T, 3, 1 > &ev)
template<typename T>
Eigen::Matrix< T, 3, 1 > MR::toEigen (const Vector3< T > &v)
template<typename T>
Eigen::Matrix< T, 3, 3 > MR::toEigen (const SymMatrix3< T > &m)
template<typename T>
Eigen::Matrix< T, 3, 3 > MR::toEigen (const Matrix3< T > &m)
template<typename T>
Matrix3< T > MR::fromEigen (const Eigen::Matrix< T, 3, 3 > &m)
template<typename T>
Eigen::Matrix< T, 4, 4 > MR::toEigen (const SymMatrix4< T > &m)
template<typename T>
Eigen::Matrix< T, 4, 4 > MR::toEigen (const Matrix4< T > &m)
template<typename T>
Matrix4< T > MR::fromEigen (const Eigen::Matrix< T, 4, 4 > &m)
template<typename T>
Vector4< T > MR::fromEigen (const Eigen::Matrix< T, 4, 1 > &ev)
template<typename T>
Eigen::Matrix< T, 4, 1 > MR::toEigen (const Vector4< T > &v)
template<typename T>
Eigen::Matrix< T, 4, 1 > MR::toEigen (const Vector3< T > &v, T w)
template<typename T>
Quaternion< T > MR::fromEigen (const Eigen::Quaternion< T > &eq)
template<typename T>
Eigen::Quaternion< T > MR::toEigen (const Quaternion< T > &q)

Detailed Description

Typedef Documentation

◆ InSphereTesterd

◆ InSphereTesterf

◆ InSphereTesteri

Enumeration Type Documentation

◆ InSphereResult

enum class MR::InSphereResult
strong

#include <MRMesh/MRInSphere.h>

the result of inSphere predicates

Enumerator
NoSphere 

the sphere is not defined: the points A, B, C are collinear or coincident, or rSq is less than the squared circumradius of triangle ABC

Outside 

the sphere exists, and the point D is strictly outside

OnSphere 

the sphere exists, and the point D is exactly on it; never returned by the simulation-of-simplicity overload, which resolves such ties into Inside or Outside

Inside 

the sphere exists, and the point D is strictly inside

Function Documentation

◆ circumcircleDiameter()

template<typename T>
T MR::circumcircleDiameter ( const Vector3< T > & a,
const Vector3< T > & b,
const Vector3< T > & c )
inlinenodiscard

#include <MRMesh/MRTriMath.h>

Computes the diameter of the triangle's ABC circumcircle

◆ circumcircleDiameterSq()

template<typename T>
T MR::circumcircleDiameterSq ( const Vector3< T > & a,
const Vector3< T > & b,
const Vector3< T > & c )
nodiscard

#include <MRMesh/MRTriMath.h>

Computes the squared diameter of the triangle's ABC circumcircle;

◆ computeBoundingBox() [1/3]

template<typename V>
Box< V > MR::computeBoundingBox ( const Vector< V, VertId > & points,
const VertBitSet & region,
const AffineXf< V > * toWorld = nullptr )
inline

#include <MRMesh/MRComputeBoundingBox.h>

passes through all region points corresponding to set bits in region and finds the minimal bounding box containing all of them; if toWorld transformation is given then returns minimal bounding box in world space

◆ computeBoundingBox() [2/3]

template<typename V>
Box< V > MR::computeBoundingBox ( const Vector< V, VertId > & points,
const VertBitSet * region = nullptr,
const AffineXf< V > * toWorld = nullptr )
inline

#include <MRMesh/MRComputeBoundingBox.h>

passes through all region points corresponding to set bits in region (if provided) and finds the minimal bounding box containing all of them; if toWorld transformation is given then returns minimal bounding box in world space

◆ computeBoundingBox() [3/3]

template<typename V>
Box< V > MR::computeBoundingBox ( const Vector< V, VertId > & points,
VertId firstVert,
VertId lastVert,
const VertBitSet * region = nullptr,
const AffineXf< V > * toWorld = nullptr )

#include <MRMesh/MRComputeBoundingBox.h>

passes through all region points 1) in the range [firstVert, lastVert) 2) corresponding to set bits in region (if provided) and finds the minimal bounding box containing all of them; if toWorld transformation is given then returns minimal bounding box in world space

◆ computeFloatCoords()

VertCoords MR::computeFloatCoords ( const ConvertToFloatVector & conv,
const Vector< Vector3i, VertId > & intCoords,
const VertBitSet * valid = nullptr )
nodiscard

#include <MRMesh/MRPrecisePredicates3.h>

converts given integer coordinates into float points in parallel

Parameters
validif given then only valid coordinates are converted, and the content of other elements in the returned vector is undefined

◆ computeIntCoords()

Vector< Vector3i, VertId > MR::computeIntCoords ( const ConvertToIntVector & conv,
const VertCoords & points,
const VertBitSet * valid = nullptr )
nodiscard

#include <MRMesh/MRPrecisePredicates3.h>

converts given points into integer coordinates in parallel

Parameters
validif given then only valid points are converted, and the content of other elements in the returned vector is undefined

◆ dihedralAngle()

template<typename T>
T MR::dihedralAngle ( const Vector3< T > & leftNorm,
const Vector3< T > & rightNorm,
const Vector3< T > & edgeVec )
nodiscard

#include <MRMesh/MRTriMath.h>

given an edge direction between two faces with given normals (not necessary of unit length), computes the dihedral angle between the faces: 0 if both faces are in the same plane, positive if the faces form convex surface, negative if the faces form concave surface; please consider the usage of faster dihedralAngleSin(e) and dihedralAngleCos(e)

◆ dihedralAngleCos()

template<typename T>
T MR::dihedralAngleCos ( const Vector3< T > & leftNorm,
const Vector3< T > & rightNorm )
nodiscard

#include <MRMesh/MRTriMath.h>

given two face normals, computes cosine of dihedral angle between the faces: 1 if both faces are in the same plane, 0 if the surface makes right angle turn at the edge, -1 if the faces overlap one another

◆ dihedralAngleSin()

template<typename T>
T MR::dihedralAngleSin ( const Vector3< T > & leftNorm,
const Vector3< T > & rightNorm,
const Vector3< T > & edgeVec )
nodiscard

#include <MRMesh/MRTriMath.h>

given an edge direction between two faces with given normals, computes sine of dihedral angle between the faces: 0 if both faces are in the same plane, positive if the faces form convex surface, negative if the faces form concave surface

◆ doTriangleSegmentIntersect()

TriangleSegmentIntersectResult MR::doTriangleSegmentIntersect ( const std::array< PreciseVertCoords, 5 > & vs)
nodiscard

#include <MRMesh/MRPrecisePredicates3.h>

checks whether triangle ABC (indices 012) and segment DE (indices 34) intersect uses simulation-of-simplicity to avoid edge-segment intersections and co-planarity

◆ findTriangleSegmentIntersectionPrecise()

Vector3f MR::findTriangleSegmentIntersectionPrecise ( const Vector3f & a,
const Vector3f & b,
const Vector3f & c,
const Vector3f & d,
const Vector3f & e,
CoordinateConverters converters )
nodiscard

#include <MRMesh/MRPrecisePredicates3.h>

finds intersection precise, using high precision int inside this function input should have intersection

◆ findTwoSegmentsIntersection()

std::optional< Vector3i > MR::findTwoSegmentsIntersection ( const Vector3i & ai,
const Vector3i & bi,
const Vector3i & ci,
const Vector3i & di )
nodiscard

#include <MRMesh/MRPrecisePredicates3.h>

given two line segments AB and CD located in one plane, finds whether they intersect and if yes, computes their common point using integer-only arithmetic

◆ fromEigen() [1/7]

template<typename T>
Vector2< T > MR::fromEigen ( const Eigen::Matrix< T, 2, 1 > & ev)
inlinenodiscard

◆ fromEigen() [2/7]

template<typename T>
Matrix2< T > MR::fromEigen ( const Eigen::Matrix< T, 2, 2 > & m)
inlinenodiscard

◆ fromEigen() [3/7]

template<typename T>
Vector3< T > MR::fromEigen ( const Eigen::Matrix< T, 3, 1 > & ev)
inlinenodiscard

◆ fromEigen() [4/7]

template<typename T>
Matrix3< T > MR::fromEigen ( const Eigen::Matrix< T, 3, 3 > & m)
inlinenodiscard

◆ fromEigen() [5/7]

template<typename T>
Vector4< T > MR::fromEigen ( const Eigen::Matrix< T, 4, 1 > & ev)
inlinenodiscard

◆ fromEigen() [6/7]

template<typename T>
Matrix4< T > MR::fromEigen ( const Eigen::Matrix< T, 4, 4 > & m)
inlinenodiscard

◆ fromEigen() [7/7]

template<typename T>
Quaternion< T > MR::fromEigen ( const Eigen::Quaternion< T > & eq)
inlinenodiscard

◆ getToFloatConverter()

ConvertToFloatVector MR::getToFloatConverter ( const Box3d & box)

#include <MRMesh/MRPrecisePredicates3.h>

creates converter from Vector3i to Vector3f in Box range (int diapason is mapped to box range)

◆ getToIntConverter()

ConvertToIntVector MR::getToIntConverter ( const Box3d & box)

#include <MRMesh/MRPrecisePredicates3.h>

creates converter from Vector3f to Vector3i in Box range (int diapason is mapped to box range)

◆ inSphere() [1/3]

InSphereResult MR::inSphere ( const std::array< PreciseVertCoords, 4 > & vs,
std::int64_t rSq )
nodiscard

#include <MRMesh/MRInSphere.h>

checks whether the point vs[3] is strictly inside the sphere of radius sqrt(rSq) passing via points vs[0], vs[1], vs[2], with the center located on the positive side of plane vs[0]vs[1]vs[2] (same convention as in the overload above); resolves "vs[3] is exactly on the sphere" ties into Inside or Outside using simulation-of-simplicity: the points are symbolically perturbed (larger perturbations of points with smaller ids; per point the z-coordinate gets larger perturbation than y than x), and the first point whose perturbation moves vs[3] off the sphere decides the answer; known deviations from full simulation-of-simplicity semantics, all answered deterministically for now (covered by sosInSphereDeviations test, to be resolved by ids in the following PRs):

  • all three points of the triangle coincide: NoSphere now, while the perturbed triangle is not degenerate and its sphere exists;
  • two points of the triangle coincide and the third one is closer than the sphere's diameter: NoSphere now, while the perturbed sphere may exist depending on the perturbation directions;
  • rSq is exactly equal to the squared circumradius of a not-degenerate triangle: perturbations change the sphere's existence, affecting both "vs[3] strictly inside" (Inside now) and "vs[3] exactly on the sphere" (Outside now); the remaining degenerate NoSphere answers are exact under full simulation-of-simplicity, because no small perturbation can create the sphere: distinct collinear triangle points, two coincident triangle points with the third one at or beyond the sphere's diameter, rSq below the squared circumradius

◆ inSphere() [2/3]

template<typename T>
std::enable_if_t< std::is_floating_point_v< T >, InSphereResult > MR::inSphere ( const Vector3< T > & a,
const Vector3< T > & b,
const Vector3< T > & c,
const Vector3< T > & d,
T rSq )
nodiscard

#include <MRMesh/MRInSphere.h>

checks whether the point d is strictly inside the sphere of radius sqrt(rSq) passing via points a, b, c, whose center is located on the positive side of plane abc, in floating-point; see the comment on InSphereTester above for the limitations

◆ inSphere() [3/3]

InSphereResult MR::inSphere ( const Vector3i & a,
const Vector3i & b,
const Vector3i & c,
const Vector3i & d,
std::int64_t rSq )
nodiscard

#include <MRMesh/MRInSphere.h>

checks whether the point D is strictly inside the sphere of radius sqrt(rSq) passing via points A, B, C, whose center is located on the positive side of plane ABC (in the half-space pointed at by cross( b - a, c - a ) from the plane); returns OnSphere when D is exactly on the sphere; cyclic permutations of (A, B, C) do not change the result, a swap of two of them selects the mirror sphere; rSq must be given in the same integer grid units as the point coordinates

◆ lookAt()

template<typename T>
AffineXf3< T > MR::lookAt ( const Vector3< T > & center,
const Vector3< T > & eye,
const Vector3< T > & up )

#include <MRMesh/MRAffineXf3.h>

computes rigid transformation xf

xf.z - directed from center to eye
xf.x - directed orthogonal to up and xf.z
xf.y - directed orthogonal to xf.z and xf.x
xf(eye) = 0

◆ makeRigidXf()

AffineXf3d MR::makeRigidXf ( const MeshPart & mp,
const AffineXf3d & meshXf )
nodiscard

#include <MRMesh/MRMakeRigidXf.h>

given a mesh part and its arbitrary transformation, computes and returns the rigid transformation that best approximates meshXf

◆ mincircleDiameterSq()

template<typename T>
T MR::mincircleDiameterSq ( const Vector3< T > & a,
const Vector3< T > & b,
const Vector3< T > & c )
nodiscard

#include <MRMesh/MRTriMath.h>

Computes the squared diameter of the smallest enclosed circle around ABC; For acute triangles it is the same as circumcircle, for obtuse triangles - the circle with the longest triangle's edge as a diameter

◆ minTriangleAngleSin()

template<typename T>
T MR::minTriangleAngleSin ( const Vector3< T > & a,
const Vector3< T > & b,
const Vector3< T > & c )
nodiscard

#include <MRMesh/MRTriMath.h>

Computes sine of minimal angle in ABC triangle, which is equal to ratio of minimal edge length to circumcircle diameter

◆ MR_BIND_TEMPLATE() [1/2]

MR::MR_BIND_TEMPLATE ( InSphereResult inSphereconst Vector3d &a, const Vector3d &b, const Vector3d &c, const Vector3d &d, double rSq)

#include <MRMesh/MRInSphere.h>

◆ MR_BIND_TEMPLATE() [2/2]

MR::MR_BIND_TEMPLATE ( InSphereResult inSphereconst Vector3f &a, const Vector3f &b, const Vector3f &c, const Vector3f &d, float rSq)

#include <MRMesh/MRInSphere.h>

◆ MR_REQUIRES_IF_SUPPORTED()

template<typename V>
MR::MR_REQUIRES_IF_SUPPORTED ( detail::AffineXf3f::IsValidTemplateArg< V > )

#include <MRMesh/MRAffineXf.h>

affine transformation: y = A*x + b, where A in VxV, and b in V

Here U == V doesn't seem to cause any issues in the C++ code, but we're still disabling it because it somehow gets emitted when generating the bindings, and results in duplicate functions in C#.

creates translation-only transformation (with identity linear component)

creates linear-only transformation (without translation)

creates transformation with given linear part with given stable point

application of the transformation to a point

applies only linear part of the transformation to given vector (e.g. to normal) skipping adding shift (b) for example if this is a rigid transformation, then only rotates input vector

computes inverse transformation

composition of two transformations: \(y = (u * v) ( x ) = u( v( x ) ) = ( u.A * ( v.A * x + v.b ) + u.b ) = ( u.A * v.A ) * x + ( u.A * v.b + u.b )\)

◆ orient3d() [1/4]

bool MR::orient3d ( const PreciseVertCoords * vs)

◆ orient3d() [2/4]

bool MR::orient3d ( const std::array< PreciseVertCoords, 4 > & vs)

#include <MRMesh/MRPrecisePredicates3.h>

first sorts the indices in ascending order, then calls the predicate for sorted points

◆ orient3d() [3/4]

bool MR::orient3d ( const Vector3i & a,
const Vector3i & b,
const Vector3i & c )

#include <MRMesh/MRPrecisePredicates3.h>

returns true if the plane with orientated triangle ABC has 0 point at the left; uses simulation-of-simplicity to avoid "0 is exactly on plane"

◆ orient3d() [4/4]

bool MR::orient3d ( const Vector3i & a,
const Vector3i & b,
const Vector3i & c,
const Vector3i & d )
inline

#include <MRMesh/MRPrecisePredicates3.h>

returns true if the plane with orientated triangle ABC has D point at the left; uses simulation-of-simplicity to avoid "D is exactly on plane"

◆ segmentIntersectionOrder()

bool MR::segmentIntersectionOrder ( const std::array< PreciseVertCoords, 8 > & vs)
nodiscard

#include <MRMesh/MRPrecisePredicates3.h>

given line segment s=01 and two triangles ta=234, tb=567 known to intersect it, finds the order of intersection using precise predicates: true: s[0], s ^ ta, s ^ tb, s[1] false: s[0], s ^ tb, s ^ ta, s[1] triangles ta and tb can have at most two shared points, all other points must be unique

◆ toEigen() [1/11]

template<typename T>
Eigen::Matrix< T, 2, 2 > MR::toEigen ( const Matrix2< T > & m)
inlinenodiscard

◆ toEigen() [2/11]

template<typename T>
Eigen::Matrix< T, 3, 3 > MR::toEigen ( const Matrix3< T > & m)
inlinenodiscard

◆ toEigen() [3/11]

template<typename T>
Eigen::Matrix< T, 4, 4 > MR::toEigen ( const Matrix4< T > & m)
inlinenodiscard

◆ toEigen() [4/11]

template<typename T>
Eigen::Quaternion< T > MR::toEigen ( const Quaternion< T > & q)
inlinenodiscard

◆ toEigen() [5/11]

template<typename T>
Eigen::Matrix< T, 2, 2 > MR::toEigen ( const SymMatrix2< T > & m)
inlinenodiscard

◆ toEigen() [6/11]

template<typename T>
Eigen::Matrix< T, 3, 3 > MR::toEigen ( const SymMatrix3< T > & m)
inlinenodiscard

◆ toEigen() [7/11]

template<typename T>
Eigen::Matrix< T, 4, 4 > MR::toEigen ( const SymMatrix4< T > & m)
inlinenodiscard

◆ toEigen() [8/11]

template<typename T>
Eigen::Matrix< T, 2, 1 > MR::toEigen ( const Vector2< T > & v)
inlinenodiscard

◆ toEigen() [9/11]

template<typename T>
Eigen::Matrix< T, 3, 1 > MR::toEigen ( const Vector3< T > & v)
inlinenodiscard

◆ toEigen() [10/11]

template<typename T>
Eigen::Matrix< T, 4, 1 > MR::toEigen ( const Vector3< T > & v,
T w )
inlinenodiscard

◆ toEigen() [11/11]

template<typename T>
Eigen::Matrix< T, 4, 1 > MR::toEigen ( const Vector4< T > & v)
inlinenodiscard

◆ triangleAspectRatio()

template<typename T>
T MR::triangleAspectRatio ( const Vector3< T > & a,
const Vector3< T > & b,
const Vector3< T > & c )
nodiscard

#include <MRMesh/MRTriMath.h>

Aspect ratio of a triangle is the ratio of the circum-radius to twice its in-radius