A Swept Hexahedral Mesh Example

The sweeper example combines many parts of the previous examples. Like A Simple Tetrahedral Mesh Example, you can generate a mesh from a water-tight, quadrilateral boundary mesh if you have topologically equivalent meshes on source and target surfaces. You may also have the sweeper project the source mesh onto the target surface if you provide a geometry evaluator derived from CMLSurfEval.

This example takes the last approach. It will take the source surface mesh shown as the top, planar surface in the left image of Figure 6 and project it to the target surface. The target surface is the bottom, planar surface in the right image.

sweep_surf.png

Figure 6: Surface Mesh for Sweep Example

The following code fragments show how to generate a hexahedral swept mesh for the above model.

    // mesh the volume
  int *hexes = NULL;
  int new_points = 0, num_hexes = 0;
  MySurfEval my_geom_eval;
  CMLSweeper sweeper(&my_geom_eval);
  ret_value = sweeper.set_boundary_mesh(num_points, points,
                                        num_quads, quads,
                                        num_source, num_target);
  if (!ret_value) {
    printf("Failed setting boundary mesh\n");
  }

Again, MySurfEval::my_geom_eval is declared a subclass of CMLSurfEval very much like in A Triangle Mesh Example. It is used as the only parameter in the constructor for the CMLSweeper class.

An earlier section of the example program read the boundary mesh from a data file as in the other examples. It is passed to the sweeper with a call to CMLSweeper::set_boundary_mesh(...).

The number of quadrilaterals, num_quads, is the total number of quads passed in. In this case, it is the sum of the number of quadrilaterals on the source surface and on the linking surface. Linking surfaces are those that connect the source to the target. They must have a regular, uniform mesh.

Since this example has no quadrilaterals on the target surface, num_target is zero.

    // generate the mesh
  if (ret_value) {
    ret_value = sweeper.generate_mesh(new_points, num_hexes);
    if (!ret_value) {
      printf("Failed generating mesh\n");
    }
  }

The CMLSweeper::generate_mesh(...) method verifies the integrity of the input boundary mesh, projects the boundary mesh to the target, and fills the volume with hexahedra. Also, CMLSweeper::generate_mesh(...) returns the number of points (new_points) and the number of hexahedra (num_hexes) generated. Use these numbers to allocate storage space for the mesh when retrieving the mesh.

    // allocate memory to accept hex mesh and retrieve it
  if (ret_value) {
    hexes  = new int [num_hexes * 8];
    points = new double [new_points * 3];
    if (hexes == NULL || points == NULL) {
      delete [] hexes;
      hexes = NULL;
      num_hexes = 0;
      
      delete [] points;
      points = NULL;
      new_points = 0;

      printf("Failed to allocate memory to receive mesh!\n");
      ret_value = false;
    }
  }

The CMLSweeper::get_mesh(...) method retrieves the swept, hexahedral mesh. The points returned include the input points; they appear as the first num_points in the list in the order they were passed to the sweeper. The hexahedron connectivity references the spatial points by their position or index in the points array. The connectivity numbering is counter-clockwise around the front face as viewed from the outside of the element. The back face is ordered so that the first-fifth, second-sixth, etc. indices form front-to-back edges of the hexahedron.

My Own Geometry Evaluator

The geometry evaluator for the planar, target surface is simple. The surface is in the x-y plane through the origin.

MySurfEval::MySurfEval()
    : a(0.0), b(0.0), c(1.0), d(0.0), surfaceArea(1600.0)
{
    // bounding box of hemisphere
  boxMin[0] = -50.0; boxMin[1] = -50.0; boxMin[2] = -0.1;
  boxMax[0] =  50.0; boxMax[1] =  50.0; boxMax[2] =  0.1;
}

The constructor initializes the coefficients of the plane equation. It also defines a bounding box and surface area for the surface although these are not used by the sweeper.

void MySurfEval::move_to_surface(double& x, double& y, double& z)
{
  double dist = a*x + b*y + c*z + d;
  if (dist > 1.0e-6)
    z -= dist;
}

Compute the distance from the point to the plane. If it is off the plane, move it in the z-direction to the plane.

bool MySurfEval::normal_at(double x,  double y,  double z,
                           double& nx, double& ny, double& nz)
{
    // normal direction (from center through point)
  nx = a;
  ny = b;
  nz = c;

    // normalized
  return true;
}

Set the normal to the plane, i.e., the coefficients of the plane equation. Return true, since the normal is normalized.

Figure 7 shows the resulting swept, hexahedral mesh from the boundary mesh in Figure 6 and the geometry evaluator, MySurfEval.

sweep_mesh.png

Figure 7: Swept Hexahedral Mesh

Other Examples

  1. A Simple Tetrahedral Mesh Example
  2. A Triangle Mesh Example
  3. An Unstructured Quadrilateral Mesh Example
  4. Curve Meshing Examples
  5. Another Triangle Mesh Example
  6. A Structured Quadrilateral Mesh Example -- Surface Mapper
  7. A Structured Quadrilateral Mesh Example -- Surface Submapper
  8. A Structured Hexahedral Mesh Example -- Volume Mapper

CAMAL 5.2-0 documentation created on 1 Jun 2010
Comments to csimsoft.com