Skip to content

Commit

Permalink
add new slice implicit fun cases, sphere, cyln, box, and plane (#1395)
Browse files Browse the repository at this point in the history
* add new slice implicit fun cases, sphere, cyln, box, and plane

* cleanup and add future cases as comments
  • Loading branch information
cyrush authored Oct 9, 2024
1 parent c11da70 commit c6d5e2e
Show file tree
Hide file tree
Showing 10 changed files with 1,463 additions and 59 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s
### Added
- Added support for unstructured topologies with mixed elements types (for example, hexs and tets).
- Added support for `pyramid` and `wedge` elements.
- Added `sphere`, `cylinder`, `box`, and `plane` options to the slice filter.
- Added a `topologies` option to the relay extract. This allows you to select which topologies are saved. This option can be used with the existing `fields` option, the result is the union of the selected topologies and fields.
- Added `near_plane` and `far_plane` to the camera details provided in Ascent::info()
- Added `add_mpi_ranks` and `add_domain_ids` filters for adding rank and domain fields to a mesh
Expand Down
231 changes: 184 additions & 47 deletions src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,44 @@ VTKHSlice::verify_params(const conduit::Node &params,

bool res = true;

res &= check_string("topology",params, info, false);
if(params.has_child("sphere"))
{
res = check_numeric("sphere/center/x",params, info, true, true) && res;
res = check_numeric("sphere/center/y",params, info, true, true) && res;
res = check_numeric("sphere/center/z",params, info, true, true) && res;
res = check_numeric("sphere/radius",params, info, true, true) && res;
}
else if(params.has_child("cylinder"))
{
res = check_numeric("cylinder/center/x",params, info, true, true) && res;
res = check_numeric("cylinder/center/y",params, info, true, true) && res;
res = check_numeric("cylinder/center/z",params, info, true, true) && res;
res = check_numeric("cylinder/axis/x",params, info, true, true) && res;
res = check_numeric("cylinder/axis/y",params, info, true, true) && res;
res = check_numeric("cylinder/axis/z",params, info, true, true) && res;
res = check_numeric("cylinder/radius",params, info, true, true) && res;
}
else if(params.has_child("box"))
{
res = check_numeric("box/min/x",params, info, true, true) && res;
res = check_numeric("box/min/y",params, info, true, true) && res;
res = check_numeric("box/min/z",params, info, true, true) && res;
res = check_numeric("box/max/x",params, info, true, true) && res;
res = check_numeric("box/max/y",params, info, true, true) && res;
res = check_numeric("box/max/z",params, info, true, true) && res;
}
else if(params.has_child("plane"))
{
res = check_numeric("plane/point/x",params, info, true, true) && res;
res = check_numeric("plane/point/y",params, info, true, true) && res;
res = check_numeric("plane/point/z",params, info, true, true) && res;
res = check_numeric("plane/normal/x",params, info, true, true) && res;
res = check_numeric("plane/normal/y",params, info, true, true) && res;
res = check_numeric("plane/normal/z",params, info, true, true) && res;
}

// old style plane
if(params.has_path("point/x_offset") && params.has_path("point/x"))
{
info["errors"]
Expand All @@ -743,20 +780,21 @@ VTKHSlice::verify_params(const conduit::Node &params,
res = check_numeric("point/y_offset",params, info, true, true) && res;
res = check_numeric("point/z_offset",params, info, true, true) && res;
}
else
// else
// {
// info["errors"]
// .append() = "Slice must specify a point for the plane.";
// res = false;
// }
if(params.has_path("normal/x"))
{
info["errors"]
.append() = "Slice must specify a point for the plane.";
res = false;
res = check_numeric("normal/x",params, info, true, true) && res;
res = check_numeric("normal/y",params, info, true, true) && res;
res = check_numeric("normal/z",params, info, true, true) && res;
}

res = check_string("topology",params, info, false) && res;

res = check_numeric("normal/x",params, info, true, true) && res;
res = check_numeric("normal/y",params, info, true, true) && res;
res = check_numeric("normal/z",params, info, true, true) && res;

std::vector<std::string> valid_paths;
// old style plane
valid_paths.push_back("point/x");
valid_paths.push_back("point/y");
valid_paths.push_back("point/z");
Expand All @@ -768,6 +806,34 @@ VTKHSlice::verify_params(const conduit::Node &params,
valid_paths.push_back("normal/z");
valid_paths.push_back("topology");

// sphere
valid_paths.push_back("sphere/center/x");
valid_paths.push_back("sphere/center/y");
valid_paths.push_back("sphere/center/z");
valid_paths.push_back("sphere/radius");
// cylinder
valid_paths.push_back("cylinder/center/x");
valid_paths.push_back("cylinder/center/y");
valid_paths.push_back("cylinder/center/z");
valid_paths.push_back("cylinder/axis/x");
valid_paths.push_back("cylinder/axis/y");
valid_paths.push_back("cylinder/axis/z");
valid_paths.push_back("cylinder/radius");
// box
valid_paths.push_back("box/min/x");
valid_paths.push_back("box/min/y");
valid_paths.push_back("box/min/z");
valid_paths.push_back("box/max/x");
valid_paths.push_back("box/max/y");
valid_paths.push_back("box/max/z");
// new style plane
valid_paths.push_back("plane/point/x");
valid_paths.push_back("plane/point/y");
valid_paths.push_back("plane/point/z");
valid_paths.push_back("plane/normal/x");
valid_paths.push_back("plane/normal/y");
valid_paths.push_back("plane/normal/z");


std::string surprises = surprise_check(valid_paths, params);

Expand Down Expand Up @@ -811,56 +877,128 @@ VTKHSlice::execute()
}

vtkh::DataSet &data = collection->dataset_by_topology(topo_name);
vtkh::Slice slicer;
vtkh::DataSet *slice_output = nullptr;

slicer.SetInput(&data);
// original implementation
if(params().has_child("point"))
{
vtkh::Slice slicer;

const Node &n_point = params()["point"];
const Node &n_normal = params()["normal"];
slicer.SetInput(&data);

using Vec3f = vtkm::Vec<vtkm::Float32,3>;
vtkm::Bounds bounds = data.GetGlobalBounds();
Vec3f point;
const Node &n_point = params()["point"];
const Node &n_normal = params()["normal"];

const float eps = 1e-5; // ensure that the slice is always inside the data set
using Vec3f = vtkm::Vec<vtkm::Float32,3>;
vtkm::Bounds bounds = data.GetGlobalBounds();
Vec3f point;

if(n_point.has_path("x_offset"))
{
float offset = get_float32(n_point["x_offset"], data_object);
std::max(-1.f, std::min(1.f, offset));
float t = (offset + 1.f) / 2.f;
t = std::max(0.f + eps, std::min(1.f - eps, t));
point[0] = bounds.X.Min + t * (bounds.X.Max - bounds.X.Min);
const float eps = 1e-5; // ensure that the slice is always inside the data set

offset = get_float32(n_point["y_offset"], data_object);
std::max(-1.f, std::min(1.f, offset));
t = (offset + 1.f) / 2.f;
t = std::max(0.f + eps, std::min(1.f - eps, t));
point[1] = bounds.Y.Min + t * (bounds.Y.Max - bounds.Y.Min);
if(n_point.has_path("x_offset"))
{
float offset = get_float32(n_point["x_offset"], data_object);
// TODO: THIS RESULT ISN'T USED, should it be offset =?
std::max(-1.f, std::min(1.f, offset));
float t = (offset + 1.f) / 2.f;
t = std::max(0.f + eps, std::min(1.f - eps, t));
point[0] = bounds.X.Min + t * (bounds.X.Max - bounds.X.Min);

offset = get_float32(n_point["y_offset"], data_object);
// TODO: THIS RESULT ISN'T USED, should it be offset =?
std::max(-1.f, std::min(1.f, offset));
t = (offset + 1.f) / 2.f;
t = std::max(0.f + eps, std::min(1.f - eps, t));
point[1] = bounds.Y.Min + t * (bounds.Y.Max - bounds.Y.Min);

offset = get_float32(n_point["z_offset"], data_object);
// TODO: THIS RESULT ISN'T USED, should it be offset =?
std::max(-1.f, std::min(1.f, offset));
t = (offset + 1.f) / 2.f;
t = std::max(0.f + eps, std::min(1.f - eps, t));
point[2] = bounds.Z.Min + t * (bounds.Z.Max - bounds.Z.Min);
}
else
{
point[0] = get_float32(n_point["x"], data_object);
point[1] = get_float32(n_point["y"], data_object);
point[2] = get_float32(n_point["z"], data_object);
}

offset = get_float32(n_point["z_offset"], data_object);
std::max(-1.f, std::min(1.f, offset));
t = (offset + 1.f) / 2.f;
t = std::max(0.f + eps, std::min(1.f - eps, t));
point[2] = bounds.Z.Min + t * (bounds.Z.Max - bounds.Z.Min);
Vec3f v_normal;
v_normal[0] = get_float32(n_normal["x"], data_object);
v_normal[1] = get_float32(n_normal["y"], data_object);
v_normal[2] = get_float32(n_normal["z"], data_object);

slicer.AddPlane(point, v_normal);

slicer.Update();

slice_output = slicer.GetOutput();
}
else
{
point[0] = get_float32(n_point["x"], data_object);
point[1] = get_float32(n_point["y"], data_object);
point[2] = get_float32(n_point["z"], data_object);
}
// implicit func slice cases
vtkh::SliceImplicit slicer;
slicer.SetInput(&data);

Vec3f v_normal;
v_normal[0] = get_float32(n_normal["x"], data_object);
v_normal[1] = get_float32(n_normal["y"], data_object);
v_normal[2] = get_float32(n_normal["z"], data_object);
if(params().has_path("sphere"))
{
const Node &sphere = params()["sphere"];
double center[3];

slicer.AddPlane(point, v_normal);
slicer.Update();
center[0] = get_float64(sphere["center/x"], data_object);
center[1] = get_float64(sphere["center/y"], data_object);
center[2] = get_float64(sphere["center/z"], data_object);
double radius = get_float64(sphere["radius"], data_object);
slicer.SetSphereSlice(center, radius);
}
else if(params().has_path("cylinder"))
{
const Node &cylinder = params()["cylinder"];
double center[3];
double axis[3];

vtkh::DataSet *slice_output = slicer.GetOutput();
center[0] = get_float64(cylinder["center/x"], data_object);
center[1] = get_float64(cylinder["center/y"], data_object);
center[2] = get_float64(cylinder["center/z"], data_object);

axis[0] = get_float64(cylinder["axis/x"], data_object);
axis[1] = get_float64(cylinder["axis/y"], data_object);
axis[2] = get_float64(cylinder["axis/z"], data_object);

double radius = get_float64(cylinder["radius"], data_object);
slicer.SetCylinderSlice(center, axis, radius);
}
else if(params().has_path("box"))
{
const Node &box = params()["box"];
vtkm::Bounds bounds;
bounds.X.Min= get_float64(box["min/x"], data_object);
bounds.Y.Min= get_float64(box["min/y"], data_object);
bounds.Z.Min= get_float64(box["min/z"], data_object);
bounds.X.Max = get_float64(box["max/x"], data_object);
bounds.Y.Max = get_float64(box["max/y"], data_object);
bounds.Z.Max = get_float64(box["max/z"], data_object);
slicer.SetBoxSlice(bounds);
}
else if(params().has_path("plane"))
{
const Node &plane= params()["plane"];
double point[3], normal[3];;

point[0] = get_float64(plane["point/x"], data_object);
point[1] = get_float64(plane["point/y"], data_object);
point[2] = get_float64(plane["point/z"], data_object);
normal[0] = get_float64(plane["normal/x"], data_object);
normal[1] = get_float64(plane["normal/y"], data_object);
normal[2] = get_float64(plane["normal/z"], data_object);
slicer.SetPlaneSlice(point, normal);
}

slicer.Update();
slice_output = slicer.GetOutput();
}
// we need to pass through the rest of the topologies, untouched,
// and add the result of this operation
VTKHCollection *new_coll = new VTKHCollection();
Expand All @@ -870,7 +1008,6 @@ VTKHSlice::execute()
DataObject *res = new DataObject(new_coll);
delete slice_output;
set_output<DataObject>(res);

}

//-----------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit c6d5e2e

Please sign in to comment.