7 Fields

7.1 Grid fields

A grid field specifies scalar or vector values at the vertices of a regular Cartesian grid and interpolates values between vertices. ArtiSynth currently provides two grid field components in artisynth.core.fields:

   ScalarGridField
   VectorGridField<T>

where T is any class implementing maspack.matrix.VectorObject. For both grid types, the value returned by getValue(p) is determined by finding the grid cell containing {\bf p} and then using trilinear interpolation of the surrounding nodal values. If {\bf p} lies outside the grid volume, then getValue(p) either returns the value at the nearest grid point {\bf p}^{\prime} (if the component property clipToGrid is set to true), or else returns a special value indicating that {\bf p} is outside the grid. This special value is ScalarGridField.OUTSIDE_GRID for scalar fields or null for vector fields.

Grid field components are implemented as wrappers around the more basic objects ScalarGrid and VectorGrid<T> defined in maspack.geometry. Applications first create one of these primary grid objects and then use it to create the field component. Instances of ScalarGrid and VectorGrid<T> can be created with constructors such as

  ScalarGrid (Vector3d widths, Vector3i res)
  ScalarGrid (Vector3d widths, Vector3i res, RigidTransform3d TCL)
  VectorGrid (Class<T> type, Vector3d widths, Vector3i res)
  VectorGrid (Class<T> type, Vector3d widths, Vector3i res, RigidTransform3d TCL)

where widths gives the grid widths along each of the x, y and z axes, res gives the number of cells along each axis, and for vector grids type is the class type of the maspack.matrix.VectorObject object parameterized by T. TCL is an optional argument which, if not null, describes the position and orientation of the grid center with respect to local coordinates; otherwise, in local coordinates the grid is centered at the origin and aligned with the x, y and z axes.

For the vector grid constructors above, T should be a fixed-size vector or matrix, such as Vector3d or Matrix3d. The variable sized objects VectorNd and MatrixNd can also be used with the aid of special wrapper classes, as described in Section 7.4.

By default, grids are axis-aligned and centered at the origin of the world coordinate system. A transform TLW can be specified to place the grid at a different position and/or orientation. TLW represents the transform from local to world coordinates and can be controlled with the methods

  void setLocalToWorld (RigidTransform3d TLW)
  RigidTransform3d getLocalToWorld()

If not specified, TLW is the identity and local and world coordinates are the same.

Once a grid is created, it can be used to instantiate a grid field component using one of the constructors

  ScalarGridField (ScalarGrid grid)
  ScalarGridField (String name, ScalarGrid grid)
  VectorGridField (VectorGrid grid)
  VectorGridField (String name, VectorGrid grid)

where grid is the primary grid and name is an optional component name. Note that the primary grid is not copied, so any subsequent changes to it will be reflected in the enclosing field component.

Once the grid field component is created, its values can be set by specifying the values at its vertices. The methods to query and set vertex values for scalar and vector fields are

  int numVertices()
  // scalar fields:
  double getVertexValue (int xi, int yj, int zk)
  double getVertexValue (int vi)
  void setVertexValue (int xi, int yj, int zk, double value)
  void setVertexValue (int vi, double value)
  // vector fields:
  T getVertexValue (int xi, int yj, int zk)
  T getVertexValue (int vi)
  void setVertexValue (int xi, int yj, int zk, T value)
  void setVertexValue (int vi, T value)

where xi, yj, and zk are the vertex’s indices along the x, y, and z axes, and vi is a general index that should be in the range 0 to field.numVertices()-1 and is related to xi, yj, and zk by

  vi = xi + nx*yj + (nx*ny)*zk,

where nx and ny are the number of vertices along the x and y axes.

When computing a grid value using getValue(p), the point p is assumed to be in either grid local or world coordinates, depending on whether the field component’s property localValuesForField is true or false (local and world coordinates are the same unless the primary grid’s local-to-world transform TLW has been set as described above).

To find the spatial position of a vertex within a grid field component, one may use the methods

  Vector3d getVertexPosition (xi, yj, zk)
  Vector3d getVertexPosition (vi)

which return the vertex position in either local or world coordinates depending on the setting of localValuesForField.

The following code example shows the creation of a ScalarGridField, with widths 5\times 5\times 10 and a cell resolution of 10\times 10\times 20, centered at the origin and whose vertex values are set to their distance from the origin, in order to create a simple distance field:

   // create a 5 x 5 x 10 grid with resolution 10 x 10 x 20 centered on the
   // origin
   ScalarGrid grid = new ScalarGrid (
      new Vector3d (5, 5, 10), new Vector3i (10, 10, 20));
   // use this to create a scalar grid field where the value at each vertex
   // is the distance from the origin
   ScalarGridField field = new ScalarGridField (grid);
   // iterate through all the vertices and set the value for each to its
   // distance from the origin, as given by the norm of it’s position
   for (int vi=0; vi<grid.numVertices(); vi++) {
      Vector3d vpos = grid.getVertexCoords (vi);
      grid.setVertexValue (vi, vpos.norm());
   }
   // add to a mech model:
   mech.addField (field);

As shown in the example and as mentioned earlier, grid field are generally added to the fields list of a MechModel.