# 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
    };

Conversation saved
HOOPSY BETA

### Hello! I'm HOOPSY

Your Docs generative AI assistant. Ask me anything about HOOPS Envision for Desktop or choose a sample question below to start a conversation:

What is HOOPS Envision for Desktop?
What are the latest release notes for HOOPS Envision for Desktop?
How do I start evaluating HOOPS Envision for Desktop?
How do I write my first sample application?
How can I get assistance?

HOOPSY may store conversations according to OpenAI's policy. Responses may not always be accurate.

HOOPSY is thinking...