UnstructGrid: A Simple Model with Results

This example shows how to build a custom memory data source.

../_images/tut_triangle_with_results.png

The geometry is a simple structure containing only a single triangle.

Three results are created and mapped to the triangle geometry:

  • A node mapped scalar result

  • A node mapped vector result

  • A displacement result

  • A transformation result

When a result has been created, it must be added to the current model specification to be visualized with the model. This example sets all four result types in the model specification. The scalar result is set to be shown as fringes.

Remember to toggle on result visibility in each part’s cee::ug::PartSettings.

    //--------------------------------------------------------------------------
    // Set up the model, state and geometry.
    // This model contains one triangle element
    //--------------------------------------------------------------------------

    // Create model and data source
    // The data source must be given a unique id and number of geometries upon construction
    cee::PtrRef<cee::ug::UnstructGridModel> ugModel = new cee::ug::UnstructGridModel();
    cee::PtrRef<cee::ug::DataSourceMemory> dataSource = new cee::ug::DataSourceMemory(1, 1);
    ugModel->setDataSource(dataSource.get());

    // Create new state with one geometry
    int stateId = 1;
    cee::PtrRef<cee::ug::DataState> state = new cee::ug::DataState(stateId, 1);
    dataSource->addState(state.get());
    ugModel->modelSpec().setStateId(stateId);

    // Create a geometry and set it in the state object
    int geometryIndex = 0;
    cee::PtrRef<cee::ug::DataGeometry> geo = new cee::ug::DataGeometry;
    state->setGeometry(geometryIndex, geo.get());

    // Add a part which consists of only one triangle

    // Define nodes
    // Add three nodes to node array. Remember to set the array size first.
    cee::PtrRef<cee::ug::DataNodes> nodes = new cee::ug::DataNodes(false);
    nodes->resize(3);
    nodes->setNode(0, cee::Vec3d(0,0,0));
    nodes->setNode(1, cee::Vec3d(1,0,0));
    nodes->setNode(2, cee::Vec3d(1,1,0));

    // Define elements
    // Connectivity array for a triangle
    int c[] = {0, 1, 2};
    std::vector<unsigned int> eltNodes1(c, c+3);    // First triangle

    // Add a triangle to the elements array. 
    cee::PtrRef<cee::ug::DataElements> elements = new cee::ug::DataElements(false, 0);   
    elements->addElement(cee::ug::Element::TRIANGLES, eltNodes1);

    // Define part. Set nodes and elements into the part object.
    int partId = 1;
    cee::PtrRef<cee::ug::DataPart> part = new cee::ug::DataPart(partId);             
    part->setNodes(nodes.get());
    part->setElements(elements.get());

    // Add the part to the geometry
    geo->addPart(part.get());

    //--------------------------------------------------------------------------
    // Create a scalar result (node mapped)
    //--------------------------------------------------------------------------

    // Create a scalar result with node mapping
    int scalarResultId = 1;
    cee::PtrRef<cee::ug::DataResultScalar> scalarResult = new cee::ug::DataResultScalar(scalarResultId, cee::ug::PER_NODE);

    // Create the scalar result part
    cee::PtrRef<cee::ug::DataPartScalar> scalarPart = new cee::ug::DataPartScalar();
    scalarPart->resize(3);
    scalarPart->setValue(0, 1.0);
    scalarPart->setValue(1, 2.0);
    scalarPart->setValue(2, 3.0);

    // Number of parts in the DataResultScalar must match number of parts in the geometry.
    // Scalar values and mapping types must also fit the corresponding part in the geometry.
    // Here the part is a single triangle with three nodes, hence a results array with three values using node mappings will fit.
    scalarResult->addPart(scalarPart.get());

    // Add a scalar result to the state
    state->results(geo.get())->addScalar(scalarResult.get());

    //--------------------------------------------------------------------------
    // Create a vector result (node mapped)
    //--------------------------------------------------------------------------

    // Create a vector result with node mapping
    int vectorResultId = 1;
    cee::PtrRef<cee::ug::DataResultVector> vectorResult = new cee::ug::DataResultVector(vectorResultId, cee::ug::PER_NODE);

    // Create the vector result part
    cee::PtrRef<cee::ug::DataPartVector> vectorPart = new cee::ug::DataPartVector();
    vectorPart->resize(3);
    vectorPart->setValue(0, cee::Vec3d(1.0, 0.0, 0.0));
    vectorPart->setValue(1, cee::Vec3d(1.0, 1.0, 0.0));
    vectorPart->setValue(2, cee::Vec3d(0.0, 2.0, 0.0));

    // Number of parts in the DataResultVector must match number of parts in the geometry.
    // Vector values and mapping types must also fit the corresponding part in the geometry.
    // Here the part is a single triangle with three nodes, hence a results array with three 
    // vectors using node mappings will fit.
    vectorResult->addPart(vectorPart.get());

    // Add a vector result to the state's result group
    state->results(geo.get())->addVector(vectorResult.get());

    //--------------------------------------------------------------------------
    // Create a displacement result 
    //--------------------------------------------------------------------------

    // Create a displacement result
    int dispResultId = 1;
    cee::PtrRef<cee::ug::DataResultDisplacement> dispResult = new cee::ug::DataResultDisplacement(dispResultId);

    // Create the displacement result part
    cee::PtrRef<cee::ug::DataPartDisplacement> dispPart = new cee::ug::DataPartDisplacement();
    dispPart->resize(3);
    dispPart->setValue(0, cee::Vec3d(1.0, 0.0, 0.0));
    dispPart->setValue(1, cee::Vec3d(0.0, 0.0, 0.0));
    dispPart->setValue(2, cee::Vec3d(0.0, 1.0, 0.0));

    // Number of parts in the DataResultDisplacement must match number of parts in the geometry.
    // Displacement values must also fit the corresponding part in the geometry.
    // Here the part is a single triangle with three nodes, hence a results array with three vectors will fit.
    dispResult->addPart(dispPart.get());

    // Add a displacement result to the state
    state->results(geo.get())->addDisplacement(dispResult.get());

    //--------------------------------------------------------------------------
    // Create a transformation result 
    //--------------------------------------------------------------------------

    // Create a transformation result
    cee::PtrRef<cee::ug::DataResultTransformation> transformationResult = new cee::ug::DataResultTransformation();

    // Create the part matrix
    cee::Mat4d partMatrix;
    partMatrix(0,3) = 1.0;
    partMatrix(1,3) = 1.0;

    // Number of parts in the DataResultTransformation must match number of parts in the geometry.
    transformationResult->addPart(partMatrix);

    // Add a transformation result to the state
    state->results(geo.get())->setTransformation(transformationResult.get());


    //--------------------------------------------------------------------------
    // Create corresponding meta data
    //--------------------------------------------------------------------------
    // When we're done creating the data source, we need to update the directory with the current
    // content
    // Set the part info
    cee::ug::PartInfo partInfo(partId, "My part");
    dataSource->directory()->setPartInfo(geometryIndex, partInfo);

    // Set the state info
    cee::ug::StateInfo stateInfo(stateId, "My state", 0.0);
    dataSource->directory()->setStateInfo(stateInfo);

    // Set the scalar result info
    cee::ug::ResultInfo scalarInfo(cee::ug::SCALAR, scalarResultId, "My scalar", cee::ug::PER_NODE);
    dataSource->directory()->setResultInfo(scalarInfo);

    // Set the vector result info
    cee::ug::ResultInfo vectorInfo(cee::ug::VECTOR, vectorResultId, "My vector", cee::ug::PER_NODE);
    dataSource->directory()->setResultInfo(vectorInfo);

    // Set the displacement result info
    cee::ug::ResultInfo displacementInfo(cee::ug::DISPLACEMENT, dispResultId, "My displacement", cee::ug::UNKNOWN_MAPPING);
    dataSource->directory()->setResultInfo(displacementInfo);

    // Set transformation result existence
    dataSource->directory()->setTransformationResult(true);

    // Set modelspec to show all results
    ugModel->modelSpec().setFringesResultId(scalarResultId);
    ugModel->modelSpec().setVectorResultId(vectorResultId);
    ugModel->modelSpec().setDisplacementResultId(dispResultId);
    ugModel->modelSpec().setTransformationResult(true);

    // Set show fringes/vectors/displacement for the part
    ugModel->partSettings(geometryIndex, partId)->setFringesVisible(true);
    ugModel->partSettings(geometryIndex, partId)->setVectorsVisible(true);
    ugModel->partSettings(geometryIndex, partId)->setDisplacementVisible(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();