Cutting plane and isosurface
This example shows how to use the isosurface and cutting plane features in a VTFx file. Isosurfaces and cutting planes are set as case properties.
Isosurface
An isosurface is defined as an area with a constant result value (e.g. pressure, temperature, velocity, density) within a volume of space. It is the 3D equivalent of a contour line.
An isosurface is derived from a scalar result and a scalar value
An isosurface can have (the same or another) scalar result shown as fringes on the surface
An isosurface can also have a vector result shown on it
Cutting Plane
A cutting plane is defined by a point and a normal
A cutting plane can have a scalar or vector result shown on it
This example creates a small part with a scalar result shown as fringes and adds an isosurface and a cutting plane. The part is set transparent to make the isosurface and cutting plane viewable.
Source file
//--------------------------------------------------------------------------------------------------
// Main function, program entry point
//--------------------------------------------------------------------------------------------------
int main()
{
// Initialize components and set up logging to console
// -------------------------------------------------------------------------
g_componentInstance = cee::CoreComponent::initialize(HOOPS_LICENSE);
cee::vtfx::VTFxComponent::initialize(g_componentInstance.get());
cee::PtrRef<cee::LogDestinationConsole> log = new cee::LogDestinationConsole();
cee::CoreComponent::logManager()->setDestination(log.get());
cee::CoreComponent::logManager()->setLevel("", 3); // Log errors, warnings and info
// Create the VTFx file
// -------------------------------------------------------------------------
cee::PtrRef<cee::vtfx::File> file = new cee::vtfx::File;
// Create VTFx file settings struct
// -------------------------------------------------------------------------
cee::vtfx::FileSettings fileSettings;
fileSettings.applicationName = "VTFx: VTFxCutIso";
fileSettings.vendorName = "My Company AS";
// Let the API create the VTFx file
cee::Str fileName = "ExampleCutIso.vtfx";
if (!file->create(fileName, fileSettings))
{
return EXIT_FAILURE;
}
// Create a single database (could have many)
// -------------------------------------------------------------------------
cee::PtrRef<cee::vtfx::Database> database = new cee::vtfx::Database(file.get(), "Only Database", 1); // database id 1
// Create a single case (could have many)
// -------------------------------------------------------------------------
cee::PtrRef<cee::vtfx::Case> singleCase = new cee::vtfx::Case(file.get(), "Only Case", 1, 1); // case id 1 using database with id 1
// Create part (a cube)
// -------------------------------------------------------------------------
{
// Create the node block
cee::PtrRef<cee::vtfx::NodeBlock> nodeBlock1 = new cee::vtfx::NodeBlock(1, false); // node block id 1
{
std::vector<float> nodesPart(NODES_PART, NODES_PART + sizeof(NODES_PART) / sizeof(NODES_PART[0]));
if (!nodeBlock1->setNodes(nodesPart))
{
return EXIT_FAILURE;
}
if (!database->writeBlock(nodeBlock1.get()))
{
return EXIT_FAILURE;
}
}
// Create the element block, using index mapping for the nodes
cee::PtrRef<cee::vtfx::ElementBlock> elementBlock1 = new cee::vtfx::ElementBlock(1, false, false); // element block id 1
{
elementBlock1->setNodeBlockId(1); // Use node block with id = 1
std::vector<int> elementNodes(CONNECTS_PART, CONNECTS_PART + sizeof(CONNECTS_PART) / sizeof(CONNECTS_PART[0]));
if (!elementBlock1->addElements(cee::vtfx::ElementBlock::HEXAHEDRONS, elementNodes))
{
return EXIT_FAILURE;
}
if (!database->writeBlock(elementBlock1.get()))
{
return EXIT_FAILURE;
}
}
}
// Write Geometry definition
// -------------------------------------------------------------------------
cee::PtrRef<cee::vtfx::GeometryBlock> geoBlock = new cee::vtfx::GeometryBlock(1); // Only one geometry per state
{
size_t geoIndex = 0;
int partId = 1;
// Set the element data
if (!geoBlock->addElementBlock(geoIndex, 1, partId)) // Add element block with id = 1.
{
return EXIT_FAILURE;
}
if (!database->writeBlock(geoBlock.get()))
{
return EXIT_FAILURE;
}
// Set geometry info
cee::PtrRef<cee::vtfx::GeometryInfoBlock> infoBlock = new cee::vtfx::GeometryInfoBlock(1); // Only one geometry per state
infoBlock->addPartInfo(geoIndex, partId, cee::Str("Cube"));
if (!database->writeBlock(infoBlock.get()))
{
return EXIT_FAILURE;
}
}
// Write state information
// -------------------------------------------------------------------------
cee::PtrRef<cee::vtfx::StateInfoBlock> stepInfo = new cee::vtfx::StateInfoBlock;
{
if (!stepInfo->addStateInfo(1, "First step", 1.0f, cee::vtfx::StateInfoBlock::TIME))
{
return EXIT_FAILURE;
}
if (!database->writeBlock(stepInfo.get()))
{
return EXIT_FAILURE;
}
}
// Write the scalar results
// -------------------------------------------------------------------------
cee::PtrRef<cee::vtfx::ResultBlock> scalarResult = new cee::vtfx::ResultBlock(1, cee::vtfx::ResultBlock::SCALAR, cee::vtfx::ResultBlock::NODE_MAPPING);
{
// Part 1 (the cube)
{
// Result values for step 1
cee::PtrRef<cee::vtfx::ResultValuesBlock> resultValuesBlockPart1Step1 = new cee::vtfx::ResultValuesBlock(1, cee::vtfx::ResultValuesBlock::SCALAR1D, false);
{
if (!resultValuesBlockPart1Step1->setMapToBlockId(1, cee::vtfx::Block::NODES)) // Use node block with id = 1
{
return EXIT_FAILURE;
}
std::vector<float> resultValues(SCALAR_PART, SCALAR_PART + sizeof(SCALAR_PART) / sizeof(SCALAR_PART[0]));
if (!resultValuesBlockPart1Step1->setResultValues(resultValues))
{
return EXIT_FAILURE;
}
if (!database->writeBlock(resultValuesBlockPart1Step1.get()))
{
return EXIT_FAILURE;
}
}
}
// Assign the result values blocks to state ids. Order is not significant.
if (!scalarResult->addResultValuesBlock(1, 1))
{
return EXIT_FAILURE;
}
scalarResult->setResultId(1);
scalarResult->setName("My scalar result");
if (!database->writeBlock(scalarResult.get()))
{
return EXIT_FAILURE;
}
}
// Write properties
// -------------------------------------------------------------------------
cee::PtrRef<cee::PropertySetCollection> vtfxProps = new cee::PropertySetCollection;
{
// Show result with id = 1 as fringes
cee::PtrRef<cee::PropertySet> scalarSelection = new cee::PropertySet("result_selection");
scalarSelection->setValue("fringes_result_id", 1);
vtfxProps->addPropertySet(scalarSelection.get());
// Show part as transparent
cee::PtrRef<cee::PropertySet> partSettings = new cee::PropertySet("part_settings");
partSettings->setValue("context_geometry_index", static_cast<unsigned int>(0));
partSettings->setValue("context_part_id", 1);
partSettings->setValue("opacity", 0.2f);
vtfxProps->addPropertySet(partSettings.get());
// Create and show cutting plane. Show result (id = 1) on plane.
cee::PtrRef<cee::PropertySet> cuttingPlane = new cee::PropertySet("cutting_plane");
cuttingPlane->setValue("point", cee::Vec3d(1.0, 1.0, 0.5));
cuttingPlane->setValue("normal", cee::Vec3d(0.0, 0.0, 1.0));
cuttingPlane->setValue("map_scalar_result_id", 1);
cuttingPlane->setValue("visible", true);
vtfxProps->addPropertySet(cuttingPlane.get());
// Create an show isosurface.
cee::PtrRef<cee::PropertySet> isosurface = new cee::PropertySet("isosurface");
isosurface->setValue("iso_scalar_result_id", 1);
isosurface->setValue("map_scalar_result_id", 1);
isosurface->setValue("iso_value", 2.0);
isosurface->setValue("visible", true);
vtfxProps->addPropertySet(isosurface.get());
// Set the camera to look at the model from negative y axis
cee::PtrRef<cee::PropertySet> camera = new cee::PropertySet("camera");
camera->setValue("eye", cee::Vec3d(1.0, -7.5, 0.5));
camera->setValue("vrp", cee::Vec3d(1.0, -5.5, 0.5));
camera->setValue("vup", cee::Vec3d(0.0, 0.0, 1.0));
vtfxProps->addPropertySet(camera.get());
// Write the block
if (!singleCase->setProperties(vtfxProps.get()))
{
return EXIT_FAILURE;
}
}
// Finally close the file
// -------------------------------------------------------------------------
if (!file->close())
{
return EXIT_FAILURE;
}
std::cout << "Exported successfully to file: " << fileName.toStdString() << std::endl;
std::cout << std::endl << "Press enter to exit..." << std::endl;
std::cin.ignore();
return EXIT_SUCCESS;
}
Header file
// Nodes
// -----------------------------------------------------------------------------
const float NODES_PART[] =
{
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
2.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f,
2.0f, 0.0f, 1.0f,
0.0f, 0.0f, 2.0f,
1.0f, 0.0f, 2.0f,
2.0f, 0.0f, 2.0f,
0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
2.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
2.0f, 1.0f, 1.0f,
0.0f, 1.0f, 2.0f,
1.0f, 1.0f, 2.0f,
2.0f, 1.0f, 2.0f,
0.0f, 2.0f, 0.0f,
1.0f, 2.0f, 0.0f,
2.0f, 2.0f, 0.0f,
0.0f, 2.0f, 1.0f,
1.0f, 2.0f, 1.0f,
2.0f, 2.0f, 1.0f,
0.0f, 2.0f, 2.0f,
1.0f, 2.0f, 2.0f,
2.0f, 2.0f, 2.0f
};
// Connectivities
// -----------------------------------------------------------------------------
const int CONNECTS_PART[] =
{
0, 1, 10, 9, 3, 4, 13, 12,
1, 2, 11, 10, 4, 5, 14, 13,
3, 4, 13, 12, 6, 7, 16, 15,
4, 5, 14, 13, 7, 8, 17, 16,
9, 10, 19, 18, 12, 13, 22, 21,
10, 11, 20, 19, 13, 14, 23, 22,
12, 13, 22, 21, 15, 16, 25, 24,
13, 14, 23, 22, 16, 17, 26, 25
};
// Scalar result values
// -----------------------------------------------------------------------------
const float SCALAR_PART[] =
{
4.0f, 4.0f, 4.0f, 3.0f, 3.0f, 3.0f, 2.0f, 2.0f, 2.0f,
3.0f, 3.0f, 3.0f, 2.0f, 2.0f, 2.0f, 1.0f, 1.0f, 1.0f,
3.0f, 3.0f, 3.0f, 2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f
};