# UnstructGrid: Create a Custom DataReader to Add Support for Your File Format

This example shows how to get your own analysis results into the `cee::ug::UnstructGridModel` by creating a `cee::ug::DataReader`.

    class SingleHexReader : public cee::ug::DataReader
    {
    public:
        bool isSupportedFileFormat(const cee::Str& /*filename*/)
        {
            return true;
        }

        bool open(const cee::Str& /*filename*/, cee::ug::Error* /*error*/)
        {
            return true;
        }

        void close()
        {
        }

        size_t geometryCount() const
        {
            return 1;
        }

        bool initializeDirectory(cee::ug::DataSourceDirectory* directory, cee::ug::Error* /*error*/)
        {
            directory->setPartInfo(0, cee::ug::PartInfo(1, "First part"));
            directory->setStateInfo(cee::ug::StateInfo(1, "First state", 0.0));
            directory->setResultInfo(cee::ug::ResultInfo(cee::ug::SCALAR, 10, "Per node result", cee::ug::PER_NODE));
    		directory->setResultInfo(cee::ug::ResultInfo(cee::ug::VECTOR, 10, "Per node result", cee::ug::PER_NODE));
            directory->setResultInfo(cee::ug::ResultInfo(cee::ug::DISPLACEMENT, 10, "Displacement result", cee::ug::PER_NODE));
    		directory->setTransformationResult(true);

            return true;
        }

        bool readGeometry(int /*stateId*/, size_t /*geometryIndex*/, cee::ug::DataGeometry* geometry, cee::ug::Error* /*error*/)
        {
            cee::PtrRef<cee::ug::DataPart> part = new cee::ug::DataPart(1);
            cee::PtrRef<cee::ug::DataElements> elements = new cee::ug::DataElements(false, 0);
            cee::PtrRef<cee::ug::DataNodes> nodes = new cee::ug::DataNodes(false);
            part->setElements(elements.get());
            part->setNodes(nodes.get());
            nodes->resize(8);
            nodes->setNode(0, cee::Vec3d(0,0,0));
            nodes->setNode(1, cee::Vec3d(1,0,0));
            nodes->setNode(2, cee::Vec3d(1,1,0));
            nodes->setNode(3, cee::Vec3d(0,1,0));
            nodes->setNode(4, cee::Vec3d(0,0,1));
            nodes->setNode(5, cee::Vec3d(1,0,1));
            nodes->setNode(6, cee::Vec3d(1,1,1));
            nodes->setNode(7, cee::Vec3d(0,1,1));

            std::vector<unsigned int> elementIndices;
            for (unsigned int i = 0; i < 8; ++i) elementIndices.push_back(i);
            elements->addElement(cee::ug::Element::HEXAHEDRONS, elementIndices);

            geometry->addPart(part.get());

            return true;
        }

        bool readScalarResult(int /*stateId*/, size_t /*geometryIndex*/, int /*resultId*/, cee::ug::DataResultScalar* scalarResult, cee::ug::Error* /*error*/)
        {
            std::vector<double> values;
            for (size_t i = 0; i < 8; ++i) values.push_back(static_cast<double>(i));

            cee::PtrRef<cee::ug::DataPartScalar> part = new cee::ug::DataPartScalar;
            part->setValues(values);
            scalarResult->addPart(part.get());

            return true;
        }

        bool readVectorResult(int /*stateId*/, size_t /*geometryIndex*/, int /*resultId*/, cee::ug::DataResultVector* vectorResult, cee::ug::Error* /*error*/)
        {
            std::vector<cee::Vec3d> values;
            for (size_t i = 0; i < 8; ++i) values.push_back(cee::Vec3d(0.2*static_cast<double>(i), 0, 0));

            cee::PtrRef<cee::ug::DataPartVector> part = new cee::ug::DataPartVector;
            part->setValues(values);
            vectorResult->addPart(part.get());

            return true;
        }

        bool readDisplacementResult(int /*stateId*/, size_t /*geometryIndex*/, int /*resultId*/, cee::ug::DataResultDisplacement* displacementResult, cee::ug::Error* /*error*/)
        {
            std::vector<cee::Vec3d> values;
            values.push_back(cee::Vec3d(0,0,0));
            values.push_back(cee::Vec3d(1.1,0,0));
            values.push_back(cee::Vec3d(1,1.2,0));
            values.push_back(cee::Vec3d(0,1,0));
            values.push_back(cee::Vec3d(0,0,1));
            values.push_back(cee::Vec3d(1,0,1));
            values.push_back(cee::Vec3d(1,1.1,1));
            values.push_back(cee::Vec3d(0,1.2,1));

            cee::PtrRef<cee::ug::DataPartDisplacement> part = new cee::ug::DataPartDisplacement;
            part->setValues(values);

            displacementResult->addPart(part.get());

            return true;
        }

        bool readTransformationResult(int /*stateId*/, size_t /*geometryIndex*/, cee::ug::DataResultTransformation* transformationResult, cee::ug::Error* /*error*/)
        {
            cee::Mat4d partMatrix = cee::Mat4d::fromRotation(cee::Vec3d(1,1,1), 0.4);
            transformationResult->addPart(partMatrix);

            return true;
        }
    };

    //--------------------------------------------------------------------------------------------------
    ///
    //--------------------------------------------------------------------------------------------------
    void TutorialRunnerMainWindow::createCustomDataReader()
    {
        //--------------------------------------------------------------------------
        // Set up the model and the data source with our custom reader
        //--------------------------------------------------------------------------

        // Create model and data source
        cee::PtrRef<cee::ug::UnstructGridModel> ugModel = new cee::ug::UnstructGridModel();
        cee::PtrRef<cee::ug::DataSourceReader> dataSource = new cee::ug::DataSourceReader(1, new SingleHexReader);
        ugModel->setDataSource(dataSource.get());

        // "Open" the file
        dataSource->open("AnyFileWillDo.xyz");

        // Get info about what is available from the reader
        const cee::ug::DataSourceDirectory* dir = dataSource->directory();
        std::vector<cee::ug::StateInfo>  stateInfos  = dir->stateInfos();
        std::vector<cee::ug::ResultInfo> scalarInfos = dir->scalarResultInfos();
        std::vector<cee::ug::ResultInfo> vectorInfos = dir->vectorResultInfos();
        std::vector<cee::ug::ResultInfo> displacementInfos = dir->displacementResultInfos();
        std::vector<cee::ug::PartInfo>   partInfos  = dir->partInfos(0);

        // Specify what to show
        ugModel->modelSpec().setStateId(stateInfos[0].id());
        ugModel->modelSpec().setFringesResultId(scalarInfos[0].id());
        ugModel->modelSpec().setVectorResultId(vectorInfos[0].id());
        ugModel->modelSpec().setDisplacementResultId(displacementInfos[0].id());
        ugModel->modelSpec().setTransformationResult(true);

        // Add model to view. Ensure that old models are removed first
        cee::vis::View* gcView = getTutorialView();
        gcView->removeAllModels();
        gcView->addModel(ugModel.get());

        ugModel->updateVisualization();

        cee::BoundingBox bb = gcView->boundingBox();
        gcView->camera().fitView(bb, cee::Vec3d(0, 0, -1), cee::Vec3d(0, 1, 0));
        gcView->camera().inputHandler()->setRotationPoint(bb.center());

        gcView->requestRedraw();

Conversation saved
HOOPSY BETA

### Hello! I'm HOOPSY

Your multilingual generative AI assistant for documentation. Ask me anything about HOOPS Envision for Desktop in your own language, 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...