Surface mesh point queries: C API¶
Quest provides the in/out and distance field queries to test a point against a surface mesh. These queries take a mesh composed of triangles in 3D and a query point. The in/out query tests whether the point is contained within the surface mesh. The distance query calculates the signed distance from the query point to the mesh.
The following examples show Quest’s C interface to these queries. The general
pattern is to set some query parameters, then pass a mint::Mesh *
or file
name string to an initialization function, call an evaluate
function
for each query point, then clean up with a finalize
function.
In/out C API¶
The in/out query operates on a 3D surface mesh, that is, triangles forming a
watertight surface enclosing a 3D volume. The in/out API utilizes integer-valued
return codes with values quest::QUEST_INOUT_SUCCESS
and
quest::QUEST_INOUT_FAILED
to indicate the success of each operation.
These examples are excerpted from <axom>/src/axom/quest/examples/quest_inout_interface.cpp
.
To get started, we first include some header files.
#include "axom/quest/interface/inout.hpp"
#ifdef AXOM_USE_MPI
#include <mpi.h>
#endif
Before initializing the query, we can set some parameters, for example, to control the logging verbosity and to set a threshold for welding vertices of the triangle mesh while generating the spatial index.
// -- Set quest_inout parameters
rc = quest::inout_set_verbose(isVerbose);
if(rc != quest::QUEST_INOUT_SUCCESS)
{
cleanAbort();
}
// Note: contour files are only supported when Axom is configured with C2C
using axom::utilities::string::endsWith;
const int dim = endsWith(fileName, ".contour") ? 2 : 3;
rc = quest::inout_set_dimension(dim);
if(rc != quest::QUEST_INOUT_SUCCESS)
{
cleanAbort();
}
rc = quest::inout_set_vertex_weld_threshold(weldThresh);
if(rc != quest::QUEST_INOUT_SUCCESS)
{
cleanAbort();
}
rc = quest::inout_set_segments_per_knot_span(segmentsPerKnotSpan);
if(rc != quest::QUEST_INOUT_SUCCESS)
{
cleanAbort();
}
By default, the verbosity is set to false
and the welding threshold is
set to 1E-9
.
We are now ready to initialize the query.
#ifdef AXOM_USE_MPI
rc = quest::inout_init(fileName, MPI_COMM_WORLD);
#else
rc = quest::inout_init(fileName);
#endif
The variable fileName
is a std::string
that indicates a triangle
mesh file. Another overload of quest::inout_init()
lets a user code pass
a reference to a mint::Mesh*
to query meshes that were previously read in
or built up. If initialization succeeded (returned
quest::QUEST_INOUT_SUCCESS
), the code can
Query the mesh bounds with
quest::inout_mesh_min_bounds(double[3])
andquest::inout_mesh_max_bounds(double[3])
.Find mesh center of mass with
quest::inout_mesh_center_of_mass(double[3])
.Test if a query point is inside the mesh surface. In this example
pt
is adouble[3]
andnumInside
is a running total.
const bool ins = quest::inout_evaluate(pt[0], pt[1], pt[2]);
numInside += ins ? 1 : 0;
Once we are done, we clean up with the following command:
quest::inout_finalize();
Signed Distance query C API¶
Excerpted from <axom>/src/axom/quest/examples/quest_signed_distance_interface.cpp
.
Quest header:
#include "axom/quest.hpp"
Before initialization, a code can set some parameters for the distance query.
Passing
true
toquest::signed_distance_set_closed_surface(bool)
lets the user read in a non-closed “terrain mesh” that divides its bounding box into “above” (positive distance to the surface mesh) and “below” (negative distance).quest::signed_distance_set_execution_space()
allows setting the execution space to run the signed distance query in. The following values are accepted:quest::SignedDistExec::CPU
runs the signed distance query on the CPU.quest::SignedDistExec::OpenMP
runs the signed distance query with multiple threads on the CPU using OpenMP. Requires building Axom with OpenMP support.quest::SignedDistExec::GPU
runs the signed distance query on the GPU, if supported. This currently requires CUDA support.
quest::signed_distance_set_allocator()
allows setting a custom Umpire allocator to allocate the underlying BVH in. The allocator should be compatible with the execution space set in the call toquest::signed_distance_set_execution_space()
.If the SLIC logging environment is in use, passing
true
toquest::signed_distance_set_verbose()
will turn on verbose logging.Use of MPI-3 shared memory can be enabled by passing
true
toquest::signed_distance_use_shared_memory()
.
The distance query must be initialized before use. In this example,
Arguments
is a POD struct containing parameters to the executable.
As with the in/out query, a user code may pass either a file name or a
reference to a mint::Mesh *
to quest::signed_distance_init()
.
int rc = quest::signed_distance_init(args.fileName, global_comm);
Once the query is initialized, the user code may retrieve mesh bounds
with quest::signed_distance_get_mesh_bounds(double* lo, double* hi)
.
Test query points against the mesh with quest::signed_distance_evaluate()
.
Here, pt
is a double[3]
, phi
is a double
array, and inode
is an integer.
phi[inode] = quest::signed_distance_evaluate(pt[0], pt[1], pt[2]);
Finally, clean up.
quest::signed_distance_finalize();