MeshFieldLinear represents a continuous piecewiselinear scalar field f
defined on a (triangular or tetrahedral) mesh; the field value changes linearly within each element E (triangle or tetrahedron), and the gradient ∇f is constant within each element.
The field is continuous across adjacent elements, but its gradient is discontinuous from one element to the other.
To represent a piecewise linear field f, we store one field value per vertex of the mesh. Each element E (triangle or tetrahedron) has (d+1) vertices, where d is the dimension of the element. For triangle, d = 2, and for tetrahedron, d = 3.
On each element E, we define a linear function fᵉ:ℝ³→ℝ using the field values at vertices of E. The gradient ∇fᵉ:ℝ³→ℝ³ is a constant map, so we write ∇fᵉ for the constant gradient vector on E as well. For a point Q in element E, we have:
f(Q) = fᵉ(Q) for Q ∈ E, ∇f(Q) = ∇fᵉ for Q ∈ E.
Notice that the domain of fᵉ is the entire space of ℝ³, while the domain of f is the underlying space of the mesh.
The following sections are details for interested readers.
For a linear triangle or tetrahedron element E in 3D, we use barycentric coordinate:
(b₀, b₁, b₂) for triangle, (b₀, b₁, b₂, b₃) for tetrahedron, ∑bᵢ = 1, bᵢ ≥ 0,
to identify a point Q that lies in the simplicial element E. The coefficient bᵢ is the weight of vertex Vᵉᵢ of the element E, where the index i is a local index within the element E, not the global index of the entire mesh. In other words, vertex Vᵉᵢ is the iᵗʰ vertex of E, not the iᵗʰ vertex among all vertices in the mesh. The point Q in E can be expressed as:
Q = ∑bᵉᵢ(Q)Vᵉᵢ,
where we indicate the barycentric coordinate of a point Q on an element E as bᵉᵢ(Q).
At a point Q in element E, the piecewise linear field f has value:
f(Q) = fᵉ(Q) = ∑bᵉᵢ(Q)Fᵉᵢ
where Fᵉᵢ is the field value at the iᵗʰ vertex of element E.
A MeshFieldLinear is a framedependent quantity. Instances of a field should be named, as with any other framedependent quantity, with a trailing _F indicating the field's frame F. The field's frame is implicitly defined to be the same as the mesh's frame on which the field is instantiated. The field's frame affects two APIs:
The field (along with its corresponding mesh) can be transformed into a new frame by invoking the TransformVertices() method on the mesh and Transform() on the field, passing the same math::RigidTransform to both.
Consider each bᵉᵢ:ℝ³→ℝ as a linear function, its gradient ∇bᵉᵢ:ℝ³→ℝ³ is a constant map, and we write ∇bᵉᵢ for the constant gradient vector. The gradient of the piecewise linear field f at a point Q in an element E is:
∇f(Q) = ∇fᵉ = ∑Fᵉᵢ∇bᵉᵢ.
At a point Q in element E, the piecewise linear field f has value:
f(Q) = ∇fᵉ⋅Q + fᵉ(0,0,0).
Notice that (0,0,0) may or may not lie in element E.
T  a valid Eigen scalar for field values. 
MeshType  the type of the meshes: TriangleSurfaceMesh or VolumeMesh. 
#include <drake/geometry/proximity/mesh_field_linear.h>
Public Member Functions  
MeshFieldLinear (std::vector< T > &&values, const MeshType *mesh, MeshGradientMode gradient_mode=MeshGradientMode::kOkOrThrow)  
Constructs a MeshFieldLinear. More...  
MeshFieldLinear (std::vector< T > &&values, const MeshType *mesh, std::vector< Vector3< T >> &&gradients)  
(Advanced) Constructor variant which receives the precomputed, perelement gradients of the field. More...  
bool  is_gradient_field_degenerate () const 
const T &  EvaluateAtVertex (int v) const 
Evaluates the field value at a vertex. More...  
template<typename B >  
promoted_numerical_t< B, T >  Evaluate (int e, const typename MeshType::template Barycentric< B > &b) const 
Evaluates the field value at a location on an element. More...  
template<typename C >  
promoted_numerical_t< C, T >  EvaluateCartesian (int e, const Vector3< C > &p_MQ) const 
Evaluates the field at a point Qp on an element. More...  
Vector3< T >  EvaluateGradient (int e) const 
Evaluates the gradient in the domain of the element indicated by e . More...  
void  Transform (const math::RigidTransform< typename MeshType::ScalarType > &X_NM) 
(Advanced) Transforms this mesh field to be measured and expressed in frame N (from its original frame M). More...  
std::unique_ptr< MeshFieldLinear >  CloneAndSetMesh (const MeshType *new_mesh) const 
Copy to a new MeshFieldLinear and set the new MeshFieldLinear to use a new compatible mesh. More...  
const MeshType &  mesh () const 
const std::vector< T > &  values () const 
bool  Equal (const MeshFieldLinear< T, MeshType > &field) const 
Checks to see whether the given MeshFieldLinear object is equal via deep exact comparison. More...  
Implements MoveConstructible, MoveAssignable  
To copy a MeshFieldLinear, use CloneAndSetMesh().  
MeshFieldLinear (MeshFieldLinear &&)=default  
MeshFieldLinear &  operator= (MeshFieldLinear &&)=default 

default 
MeshFieldLinear  (  std::vector< T > &&  values, 
const MeshType *  mesh,  
MeshGradientMode  gradient_mode = MeshGradientMode::kOkOrThrow 

) 
Constructs a MeshFieldLinear.
values  The field value at each vertex of the mesh. 
mesh  The mesh M to which this field refers. 
gradient_mode  Whether to calculate gradient field, and how to report failures. Calculating gradient allows EvaluateCartesian() to evaluate the field directly instead of converting Cartesian coordinates to barycentric coordinates first. If no gradient is calculated, EvaluateCartesian() will be slower. On the other hand, calculating gradient requires certain quality from mesh elements. If the mesh quality is very poor, calculating gradient may either throw or mark the gradient field as degenerate. See is_gradient_field_degenerate(). The default is to succeed or throw. 
You can use the parameter gradient_mode
to trade time and space of this constructor for speed of EvaluateCartesian(). For gradient_mode
!= kNone
(kOkOrThrow
by default, or kOkOrMarkDegenerate
similarly) and good mesh quality, this constructor will take longer time to compute and will store one fieldgradient vector for each element in the mesh, but the interpolation by EvaluateCartesian() will be faster because we will use a dot product with the Cartesian coordinates directly, instead of solving a linear system to convert Cartesian coordinates to barycentric coordinates first.
When gradient_mode
!= kNone
and gradient calculation succeeds, EvaluateGradient() on a mesh element will be available. Otherwise, EvaluateGradient() will throw
.
The following features are independent of the choice of gradient_mode
.
gradient_mode
!= kNone
, a poor quality element can cause numerical errors in calculating field gradients. A poor quality element is defined as having an extremely large aspect ratio R=E/h, where E is the longest edge length and h is the shortest height. A height of a triangular element is the distance between a vertex and its opposite edge. A height of a tetrahedral element is the distance between a vertex and its opposite triangular face. For example, an extremely skinny triangle has poor quality, and a tetrahedron with four vertices almost coplanar also has poor quality. The exact threshold of the acceptable aspect ratio depends on many factors including the underlying scalar type and the exact shape and size of the element; however, a rough conservative estimation is 1e12.mesh
is nonnull, and the number of entries in values
is the same as the number of vertices of the mesh. MeshFieldLinear  (  std::vector< T > &&  values, 
const MeshType *  mesh,  
std::vector< Vector3< T >> &&  gradients  
) 
(Advanced) Constructor variant which receives the precomputed, perelement gradients of the field.
gradients[i]
is the gradient of the linear function defined on the ith element of mesh
.
The caller is responsible for making sure that the gradients are consistent with the field values
defined at the vertices. Failure to do so will lead to nonsensical results when evaluating the field near a mesh vertex as opposed to at the vertex.
As with the other constructor, mesh
must remain alive at least as long as this field instance.
std::unique_ptr<MeshFieldLinear> CloneAndSetMesh  (  const MeshType *  new_mesh  )  const 
Copy to a new MeshFieldLinear and set the new MeshFieldLinear to use a new compatible mesh.
MeshFieldLinear needs a mesh to operate; however, MeshFieldLinear does not own the mesh. In fact, several MeshFieldLinear objects can use the same mesh.
bool Equal  (  const MeshFieldLinear< T, MeshType > &  field  )  const 
Checks to see whether the given MeshFieldLinear object is equal via deep exact comparison.
The name of the objects are exempt from this comparison. NaNs are treated as not equal as per the IEEE standard.
field  The field for comparison. 
true
if the given field is equal. promoted_numerical_t<B, T> Evaluate  (  int  e, 
const typename MeshType::template Barycentric< B > &  b  
)  const 
Evaluates the field value at a location on an element.
The return type depends on both the field's scalar type T
and the Barycentric coordinate type B
. See promoted_numerical_t for details.
e  The index of the element. 
b  The barycentric coordinates. 
std::exception  if MeshType doesn't support Barycentric coordinates. 
B  The scalar type for the barycentric coordinate. 
const T& EvaluateAtVertex  (  int  v  )  const 
Evaluates the field value at a vertex.
v  The index of the vertex. 
promoted_numerical_t<C, T> EvaluateCartesian  (  int  e, 
const Vector3< C > &  p_MQ  
)  const 
Evaluates the field at a point Qp on an element.
If the element is a tetrahedron, Qp is the input point Q. If the element is a triangle, Qp is the projection of Q on the triangle's plane.
If gradients have been calculated, it evaluates the field value directly. Otherwise, it converts Cartesian coordinates to barycentric coordinates for barycentric interpolation.
The return type depends on both the field's scalar type T
and the Cartesian coordinate type C
. See promoted_numerical_t for details.
e  The index of the element. 
p_MQ  The position of point Q expressed in frame M, in Cartesian coordinates. M is the frame of the mesh. 
std::exception  if the field does not have gradients defined and the MeshType doesn't support Barycentric coordinates. 
Evaluates the gradient in the domain of the element indicated by e
.
The gradient is a vector in R³ expressed in frame M. For surface meshes, it will particularly lie parallel to the plane of the corresponding triangle.
std::exception  if the gradient vector was not calculated. 
std::exception  if the gradient field is marked degenerate. 
bool is_gradient_field_degenerate  (  )  const 
const MeshType& mesh  (  )  const 

default 
void Transform  (  const math::RigidTransform< typename MeshType::ScalarType > &  X_NM  ) 
(Advanced) Transforms this mesh field to be measured and expressed in frame N (from its original frame M).
See the class documentation for further details.
const std::vector<T>& values  (  )  const 