@@ -198,6 +198,7 @@ class MeshFieldLinear {
198
198
static_cast <int >(values_at_Mo_.size ()));
199
199
}
200
200
}
201
+ CalcMinAndMaxValues ();
201
202
}
202
203
203
204
/* * (Advanced) Constructor variant which receives the pre-computed,
@@ -224,6 +225,7 @@ class MeshFieldLinear {
224
225
DRAKE_DEMAND (static_cast <int >(gradients_.size ()) == mesh_->num_elements ());
225
226
226
227
CalcValueAtMeshOriginForAllElements ();
228
+ CalcMinAndMaxValues ();
227
229
}
228
230
229
231
/* * @returns true iff the gradient field could not be computed, and the mesh
@@ -238,10 +240,40 @@ class MeshFieldLinear {
238
240
@pre v ∈ [0, this->mesh().num_vertices()).
239
241
*/
240
242
const T& EvaluateAtVertex (int v) const {
241
- DRAKE_ASSERT (v >= 0 && v < mesh_->num_vertices ());
243
+ DRAKE_DEMAND (v >= 0 && v < mesh_->num_vertices ());
242
244
return values_[v];
243
245
}
244
246
247
+ /* * (Advanced) Evaluates the minimum field value on an element.
248
+ @param e The index of the element.
249
+ @pre e ∈ [0, this->mesh().num_elements()).
250
+ */
251
+ const T& EvaluateMin (int e) const {
252
+ DRAKE_DEMAND (e >= 0 && e < mesh_->num_elements ());
253
+ return min_values_[e];
254
+ }
255
+
256
+ /* * (Advanced) Evaluates the maximum field value on an element.
257
+ @param e The index of the element.
258
+ @pre e ∈ [0, this->mesh().num_elements()).
259
+ */
260
+ const T& EvaluateMax (int e) const {
261
+ DRAKE_DEMAND (e >= 0 && e < mesh_->num_elements ());
262
+ return max_values_[e];
263
+ }
264
+
265
+ /* * (Advanced) Evaluates the linear function associated with element e at the
266
+ mesh origin Mo.
267
+ @param e The index of the element.
268
+ @pre e ∈ [0, this->mesh().num_elements()).
269
+ @pre The field has valid gradients.
270
+ */
271
+ const T& EvaluateAtMo (int e) const {
272
+ DRAKE_DEMAND (e >= 0 && e < mesh_->num_elements ());
273
+ DRAKE_DEMAND (e < ssize (values_at_Mo_));
274
+ return values_at_Mo_[e];
275
+ }
276
+
245
277
/* * Evaluates the field value at a location on an element.
246
278
247
279
The return type depends on both the field's scalar type `T` and the
@@ -361,8 +393,14 @@ class MeshFieldLinear {
361
393
return new_mesh_field;
362
394
}
363
395
396
+ /* * The mesh M to which this field refers. */
364
397
const MeshType& mesh () const { return *mesh_; }
398
+ /* * The field value at each vertex. */
365
399
const std::vector<T>& values () const { return values_; }
400
+ /* * The minimum field value on each element. */
401
+ const std::vector<T>& min_values () const { return min_values_; }
402
+ /* * The maximum field value on each element. */
403
+ const std::vector<T>& max_values () const { return max_values_; }
366
404
367
405
// TODO(#12173): Consider NaN==NaN to be true in equality tests.
368
406
/* * Checks to see whether the given MeshFieldLinear object is equal via deep
@@ -416,6 +454,25 @@ class MeshFieldLinear {
416
454
}
417
455
}
418
456
457
+ void CalcMinAndMaxValues () {
458
+ min_values_.clear ();
459
+ max_values_.clear ();
460
+ min_values_.reserve (this ->mesh ().num_elements ());
461
+ max_values_.reserve (this ->mesh ().num_elements ());
462
+ for (int e = 0 ; e < this ->mesh ().num_elements (); ++e) {
463
+ T min, max;
464
+ min = max = values_[this ->mesh ().element (e).vertex (0 )];
465
+
466
+ for (int i = 1 ; i < mesh ().element (e).num_vertices (); ++i) {
467
+ min = std::min (min, values_[this ->mesh ().element (e).vertex (i)]);
468
+ max = std::max (max, values_[this ->mesh ().element (e).vertex (i)]);
469
+ }
470
+
471
+ min_values_.emplace_back (min);
472
+ max_values_.emplace_back (max);
473
+ }
474
+ }
475
+
419
476
std::optional<Vector3<T>> MaybeCalcGradientVector (int e) const {
420
477
// In the case of the PolygonSurfaceMesh, where kVertexPerElement is marked
421
478
// as "indeterminate" (aka -1), we'll simply use the first three vertices.
@@ -454,6 +511,12 @@ class MeshFieldLinear {
454
511
// The field values are indexed in the same way as vertices, i.e.,
455
512
// values_[i] is the field value for the mesh vertices_[i].
456
513
std::vector<T> values_;
514
+ // Stores the minimum value of the field for each element, i.e.,
515
+ // min_values_[i] is the minimum field value on the domain of elements_[i].
516
+ std::vector<T> min_values_;
517
+ // Stores the maximum value of the field for each element, i.e.,
518
+ // min_values_[i] is the minimum field value on the domain of elements_[i].
519
+ std::vector<T> max_values_;
457
520
// The gradients are indexed in the same way as elements, i.e.,
458
521
// gradients_[i] is the gradient vector on elements_[i]. The elements could
459
522
// be tetrahedra for VolumeMesh or triangles for TriangleSurfaceMesh.
0 commit comments