Exemplo n.º 1
0
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivWellFracturePartMgr::createSingleColorSurfacePart(const std::vector<cvf::uint>&  triangleIndices,
                                                                         const std::vector<cvf::Vec3f>& nodeCoords,
                                                                         const cvf::Color3f&            color)
{
    cvf::ref<cvf::DrawableGeo> geo = buildDrawableGeoFromTriangles(triangleIndices, nodeCoords);

    cvf::ref<cvf::Part> surfacePart = new cvf::Part(0, "FractureSurfacePart_stimPlan");
    surfacePart->setDrawable(geo.p());
    surfacePart->setPriority(RivPartPriority::PartType::BaseLevel);
    surfacePart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture));

    cvf::Color4f                fractureColor = cvf::Color4f(color);
    caf::SurfaceEffectGenerator surfaceGen(fractureColor, caf::PO_1);
    cvf::ref<cvf::Effect>       eff = surfaceGen.generateCachedEffect();
    surfacePart->setEffect(eff.p());

    return surfacePart;
}
Exemplo n.º 2
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RivWellHeadPartMgr::buildWellHeadParts(size_t frameIndex)
{
    m_wellHeadParts.clear();

    if (m_rimReservoirView.isNull()) return;

    RigReservoir* rigReservoir = m_rimReservoirView->eclipseCase()->reservoirData();

    RimWell* well = m_rimWell;

    RigWellResults* wellResults = well->wellResults();

    if (wellResults->m_staticWellCells.m_wellResultBranches.size() == 0)
    {
        wellResults->computeStaticWellCellPath();
    }
    if (wellResults->m_staticWellCells.m_wellResultBranches.size() == 0) return;

    if (!wellResults->hasWellResult(frameIndex)) return;

    const RigWellResultFrame& wellResultFrame = wellResults->wellResultFrame(frameIndex);

    const RigCell& whCell = rigReservoir->cellFromWellResultCell(wellResultFrame.m_wellHead);

    double characteristicCellSize = rigReservoir->mainGrid()->characteristicCellSize();

    // Match this position with pipe start position in RivWellPipesPartMgr::calculateWellPipeCenterline()
    cvf::Vec3d whStartPos = whCell.faceCenter(cvf::StructGridInterface::NEG_K);
    whStartPos -= rigReservoir->mainGrid()->displayModelOffset();
    whStartPos.transformPoint(m_scaleTransform->worldTransform());

    cvf::Vec3d whEndPos = whStartPos; 
    whEndPos.z() += characteristicCellSize * m_rimReservoirView->wellCollection()->wellHeadScaleFactor();

    cvf::Vec3d arrowPosition = whEndPos;
    arrowPosition.z() += 2.0;

    // Well head pipe geometry
    {
        cvf::ref<cvf::Vec3dArray> wellHeadPipeCoords = new cvf::Vec3dArray;
        wellHeadPipeCoords->resize(2);
        wellHeadPipeCoords->set(0, whStartPos);
        wellHeadPipeCoords->set(1, whEndPos);

        cvf::ref<RivPipeGeometryGenerator> pipeGeomGenerator = new RivPipeGeometryGenerator;
        pipeGeomGenerator->setPipeCenterCoords(wellHeadPipeCoords.p());
        pipeGeomGenerator->setPipeColor(well->wellPipeColor());
        pipeGeomGenerator->setCrossSectionVertexCount(m_rimReservoirView->wellCollection()->pipeCrossSectionVertexCount());

        double pipeRadius = m_rimReservoirView->wellCollection()->pipeRadiusScaleFactor() * m_rimWell->pipeRadiusScaleFactor() * characteristicCellSize;
        pipeGeomGenerator->setRadius(pipeRadius);

        cvf::ref<cvf::DrawableGeo> pipeSurface = pipeGeomGenerator->createPipeSurface();
        cvf::ref<cvf::DrawableGeo> centerLineDrawable = pipeGeomGenerator->createCenterLine();

        if (pipeSurface.notNull())
        {
            cvf::ref<cvf::Part> part = new cvf::Part;
            part->setName("RivWellHeadPartMgr: surface " + cvfqt::Utils::fromQString(well->name()));
            part->setDrawable(pipeSurface.p());

            caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(well->wellPipeColor()), true);
            cvf::ref<cvf::Effect> eff = surfaceGen.generateEffect();

            part->setEffect(eff.p());

            m_wellHeadParts.push_back(part.p());
        }

        if (centerLineDrawable.notNull())
        {
            cvf::ref<cvf::Part> part = new cvf::Part;
            part->setName("RivWellHeadPartMgr: centerline " + cvfqt::Utils::fromQString(well->name()));
            part->setDrawable(centerLineDrawable.p());

            caf::MeshEffectGenerator meshGen(well->wellPipeColor());
            cvf::ref<cvf::Effect> eff = meshGen.generateEffect();

            part->setEffect(eff.p());

            m_wellHeadParts.push_back(part.p());
        }
    }

    double arrowLength = characteristicCellSize * m_rimReservoirView->wellCollection()->wellHeadScaleFactor();
    cvf::Vec3d textPosition = arrowPosition;
    textPosition.z() += 1.2 * arrowLength;
    
    cvf::Mat4f matr;
    if (wellResultFrame.m_productionType != RigWellResultFrame::PRODUCER)
    {
        matr = cvf::Mat4f::fromRotation(cvf::Vec3f(1.0f, 0.0f, 0.0f), cvf::Math::toRadians(180.0f));
    }

    double ijScaleFactor = arrowLength / 6;
    matr(0, 0) *= ijScaleFactor;
    matr(1, 1) *= ijScaleFactor;
    matr(2, 2) *= arrowLength;

    if (wellResultFrame.m_productionType != RigWellResultFrame::PRODUCER)
    {
        arrowPosition.z() += arrowLength;
    }

    matr.setTranslation(cvf::Vec3f(arrowPosition));

    cvf::GeometryBuilderFaceList builder;
    cvf::ArrowGenerator gen;
    gen.setShaftRelativeRadius(0.5f);
    gen.setHeadRelativeRadius(1.0f);
    gen.setHeadRelativeLength(0.4f);
    gen.setNumSlices(m_rimReservoirView->wellCollection()->pipeCrossSectionVertexCount());
    gen.generate(&builder);

    cvf::ref<cvf::Vec3fArray> vertices = builder.vertices();
    cvf::ref<cvf::UIntArray> faceList = builder.faceList();

    size_t i;
    for (i = 0; i < vertices->size(); i++)
    {
        cvf::Vec3f v = vertices->get(i);
        v.transformPoint(matr);
        vertices->set(i, v);
    }

    cvf::ref<cvf::DrawableGeo> geo1 = new cvf::DrawableGeo;
    geo1->setVertexArray(vertices.p());   
    geo1->setFromFaceList(*faceList);
    geo1->computeNormals();


    {
        cvf::ref<cvf::Part> part = new cvf::Part;
        part->setName("RivWellHeadPartMgr: arrow " + cvfqt::Utils::fromQString(well->name()));
        part->setDrawable(geo1.p());

        cvf::Color4f headColor(cvf::Color3::GRAY);
        if (wellResultFrame.m_isOpen)
        {
            if (wellResultFrame.m_productionType == RigWellResultFrame::PRODUCER)
            {
                headColor = cvf::Color4f(cvf::Color3::GREEN);
            }
            else if (wellResultFrame.m_productionType == RigWellResultFrame::OIL_INJECTOR)
            {
                headColor = cvf::Color4f(cvf::Color3::ORANGE);
            }
            else if (wellResultFrame.m_productionType == RigWellResultFrame::GAS_INJECTOR)
            {
                headColor = cvf::Color4f(cvf::Color3::RED);
            }
            else if (wellResultFrame.m_productionType == RigWellResultFrame::WATER_INJECTOR)
            {
                headColor = cvf::Color4f(cvf::Color3::BLUE);
            }
        }

        caf::SurfaceEffectGenerator surfaceGen(headColor, true);
        cvf::ref<cvf::Effect> eff = surfaceGen.generateEffect();

        part->setEffect(eff.p());
        m_wellHeadParts.push_back(part.p());
    }

    if (m_rimReservoirView->wellCollection()->showWellLabel() && well->showWellLabel())
    {
        cvf::ref<cvf::DrawableText> drawableText = new cvf::DrawableText;
        drawableText->setFont(m_font.p());
        drawableText->setCheckPosVisible(false);
        drawableText->setDrawBorder(false);
        drawableText->setDrawBackground(false);
        drawableText->setVerticalAlignment(cvf::TextDrawer::CENTER);
        drawableText->setTextColor(cvf::Color3::WHITE);

        cvf::String cvfString = cvfqt::Utils::fromQString(well->name());

        cvf::Vec3f textCoord(textPosition);
        drawableText->addText(cvfString, textCoord);

        cvf::ref<cvf::Part> part = new cvf::Part;
        part->setName("RivWellHeadPartMgr: text " + cvfString);
        part->setDrawable(drawableText.p());

        cvf::ref<cvf::Effect> eff = new cvf::Effect;

        part->setEffect(eff.p());
        part->setPriority(1);

        m_wellHeadParts.push_back(part.p());
    }
}
Exemplo n.º 3
0
//--------------------------------------------------------------------------------------------------
/// Create mask for the parts outside the grid cells of the reservoir
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivWellFracturePartMgr::createMaskOfFractureOutsideGrid(const RimEclipseView& activeView)
{
    cvf::Mat4d frMx = m_rimFracture->transformMatrix();

    std::vector<cvf::Vec3f> maskTriangles;

    auto displCoordTrans = activeView.displayCoordTransform();

    for (const auto& visibleFracturePolygon : m_visibleFracturePolygons)
    {
        std::vector<cvf::Vec3d> borderOfFractureCellPolygonLocalCsd;
        cvf::BoundingBox        frBBox;

        for (const auto& pv : visibleFracturePolygon)
        {
            cvf::Vec3d pvd(pv);
            borderOfFractureCellPolygonLocalCsd.push_back(pvd);
            pvd.transformPoint(frMx);
            frBBox.add(pvd);
        }

        std::vector<std::vector<cvf::Vec3d>> clippedPolygons;

        std::vector<size_t> cellCandidates;
        activeView.mainGrid()->findIntersectingCells(frBBox, &cellCandidates);
        if (cellCandidates.empty())
        {
            clippedPolygons.push_back(borderOfFractureCellPolygonLocalCsd);
        }
        else
        {
            // Check if fracture polygon is fully inside the grid

            bool allPointsInsideGrid = true;
            for (const auto& v : borderOfFractureCellPolygonLocalCsd)
            {
                auto         pointInDomainCoords = v.getTransformedPoint(frMx);
                bool         pointInsideGrid     = false;
                RigMainGrid* mainGrid            = activeView.mainGrid();

                std::array<cvf::Vec3d, 8> corners;
                for (size_t cellIndex : cellCandidates)
                {
                    mainGrid->cellCornerVertices(cellIndex, corners.data());

                    if (RigHexIntersectionTools::isPointInCell(pointInDomainCoords, corners.data()))
                    {
                        pointInsideGrid = true;
                        break;
                    }
                }

                if (!pointInsideGrid)
                {
                    allPointsInsideGrid = false;
                    break;
                }
            }

            if (!allPointsInsideGrid)
            {
                std::vector<std::vector<cvf::Vec3d>> allEclCellPolygons;
                for (size_t resCellIdx : cellCandidates)
                {
                    // Calculate Eclipse cell intersection with fracture plane

                    std::array<cvf::Vec3d, 8> corners;
                    activeView.mainGrid()->cellCornerVertices(resCellIdx, corners.data());

                    std::vector<std::vector<cvf::Vec3d>> eclCellPolygons;
                    bool hasIntersection = RigHexIntersectionTools::planeHexIntersectionPolygons(corners, frMx, eclCellPolygons);

                    if (!hasIntersection || eclCellPolygons.empty()) continue;

                    // Transform eclCell - plane intersection onto fracture

                    cvf::Mat4d invertedTransformMatrix = frMx.getInverted();
                    for (std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons)
                    {
                        for (cvf::Vec3d& v : eclCellPolygon)
                        {
                            v.transformPoint(invertedTransformMatrix);
                        }

                        allEclCellPolygons.push_back(eclCellPolygon);
                    }
                }

                {
                    std::vector<std::vector<cvf::Vec3d>> polys =
                        RigCellGeometryTools::subtractPolygons(borderOfFractureCellPolygonLocalCsd, allEclCellPolygons);

                    for (const auto& polygon : polys)
                    {
                        clippedPolygons.push_back(polygon);
                    }
                }
            }
        }

        for (auto& clippedPolygon : clippedPolygons)
        {
            for (auto& point : clippedPolygon)
            {
                point.transformPoint(frMx);
            }
        }

        // Create triangles from the clipped polygons
        cvf::Vec3d fractureNormal = cvf::Vec3d(frMx.col(2));

        for (const auto& clippedPolygon : clippedPolygons)
        {
            cvf::EarClipTesselator tess;
            tess.setNormal(fractureNormal);
            cvf::Vec3dArray cvfNodes(clippedPolygon);
            tess.setGlobalNodeArray(cvfNodes);
            std::vector<size_t> polyIndexes;
            for (size_t idx = 0; idx < clippedPolygon.size(); ++idx)
                polyIndexes.push_back(idx);
            tess.setPolygonIndices(polyIndexes);

            std::vector<size_t> triangleIndices;
            tess.calculateTriangles(&triangleIndices);

            for (size_t idx : triangleIndices)
            {
                maskTriangles.push_back(cvf::Vec3f(displCoordTrans->transformToDisplayCoord(clippedPolygon[idx])));
            }
        }
    }

    if (maskTriangles.size() >= 3)
    {
        cvf::ref<cvf::DrawableGeo> maskTriangleGeo = new cvf::DrawableGeo;
        maskTriangleGeo->setVertexArray(new cvf::Vec3fArray(maskTriangles));

        cvf::ref<cvf::PrimitiveSetDirect> primitives = new cvf::PrimitiveSetDirect(cvf::PT_TRIANGLES);
        primitives->setIndexCount(maskTriangles.size());
        maskTriangleGeo->addPrimitiveSet(primitives.p());
        maskTriangleGeo->computeNormals();

        cvf::ref<cvf::Part> containmentMaskPart = new cvf::Part(0, "FractureContainmentMaskPart");
        containmentMaskPart->setDrawable(maskTriangleGeo.p());
        containmentMaskPart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture));

        cvf::Color4f maskColor = cvf::Color4f(cvf::Color3f(cvf::Color3::GRAY));

        caf::SurfaceEffectGenerator surfaceGen(maskColor, caf::PO_NONE);
        cvf::ref<cvf::Effect>       eff = surfaceGen.generateCachedEffect();
        containmentMaskPart->setEffect(eff.p());

        return containmentMaskPart;
    }

    return nullptr;
}
Exemplo n.º 4
0
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivWellFracturePartMgr::createContainmentMaskPart(const RimEclipseView& activeView)
{
    std::vector<cvf::Vec3d> borderPolygonLocalCS = fractureBorderPolygon();
    cvf::Mat4d              frMx                 = m_rimFracture->transformMatrix();

    cvf::BoundingBox        frBBox;
    std::vector<cvf::Vec3d> borderPolygonLocalCsd;
    for (const auto& pv : borderPolygonLocalCS)
    {
        cvf::Vec3d pvd(pv);
        borderPolygonLocalCsd.push_back(pvd);
        pvd.transformPoint(frMx);
        frBBox.add(pvd);
    }

    std::vector<size_t> cellCandidates;
    activeView.mainGrid()->findIntersectingCells(frBBox, &cellCandidates);

    auto displCoordTrans = activeView.displayCoordTransform();

    std::vector<cvf::Vec3f> maskTriangles;

    RimEclipseCase* eclipseCase = nullptr;
    activeView.firstAncestorOrThisOfType(eclipseCase);
    auto reservoirCellIndicesOpenForFlow = RimFractureContainmentTools::reservoirCellIndicesOpenForFlow(eclipseCase, m_rimFracture);

    for (size_t resCellIdx : cellCandidates)
    {
        if (!m_rimFracture->isEclipseCellOpenForFlow(activeView.mainGrid(), reservoirCellIndicesOpenForFlow, resCellIdx))
        {
            // Calculate Eclipse cell intersection with fracture plane

            std::array<cvf::Vec3d, 8> corners;
            activeView.mainGrid()->cellCornerVertices(resCellIdx, corners.data());

            std::vector<std::vector<cvf::Vec3d>> eclCellPolygons;
            bool hasIntersection = RigHexIntersectionTools::planeHexIntersectionPolygons(corners, frMx, eclCellPolygons);

            if (!hasIntersection || eclCellPolygons.empty()) continue;

            // Transform eclCell - plane intersection onto fracture

            cvf::Mat4d invertedTransformMatrix = frMx.getInverted();
            for (std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons)
            {
                for (cvf::Vec3d& v : eclCellPolygon)
                {
                    v.transformPoint(invertedTransformMatrix);
                }
            }

            cvf::Vec3d fractureNormal = cvf::Vec3d(frMx.col(2));
            for (const std::vector<cvf::Vec3d>& eclCellPolygon : eclCellPolygons)
            {
                // Clip Eclipse cell polygon with fracture border

                std::vector<std::vector<cvf::Vec3d>> clippedPolygons =
                    RigCellGeometryTools::intersectPolygons(eclCellPolygon, borderPolygonLocalCsd);
                for (auto& clippedPolygon : clippedPolygons)
                {
                    for (auto& v : clippedPolygon)
                    {
                        v.transformPoint(frMx);
                    }
                }

                // Create triangles from the clipped polygons

                for (auto& clippedPolygon : clippedPolygons)
                {
                    cvf::EarClipTesselator tess;
                    tess.setNormal(fractureNormal);
                    cvf::Vec3dArray cvfNodes(clippedPolygon);
                    tess.setGlobalNodeArray(cvfNodes);
                    std::vector<size_t> polyIndexes;
                    for (size_t idx = 0; idx < clippedPolygon.size(); ++idx)
                        polyIndexes.push_back(idx);
                    tess.setPolygonIndices(polyIndexes);

                    std::vector<size_t> triangleIndices;
                    tess.calculateTriangles(&triangleIndices);

                    for (size_t idx : triangleIndices)
                    {
                        maskTriangles.push_back(cvf::Vec3f(displCoordTrans->transformToDisplayCoord(clippedPolygon[idx])));
                    }
                }
            }
        }
    }

    if (maskTriangles.size() >= 3)
    {
        cvf::ref<cvf::DrawableGeo> maskTriangleGeo = new cvf::DrawableGeo;
        maskTriangleGeo->setVertexArray(new cvf::Vec3fArray(maskTriangles));

        cvf::ref<cvf::PrimitiveSetDirect> primitives = new cvf::PrimitiveSetDirect(cvf::PT_TRIANGLES);
        primitives->setIndexCount(maskTriangles.size());
        maskTriangleGeo->addPrimitiveSet(primitives.p());
        maskTriangleGeo->computeNormals();

        cvf::ref<cvf::Part> containmentMaskPart = new cvf::Part(0, "FractureContainmentMaskPart");
        containmentMaskPart->setDrawable(maskTriangleGeo.p());
        containmentMaskPart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture));

        cvf::Color4f maskColor = cvf::Color4f(cvf::Color3f(cvf::Color3::GRAY));

        caf::SurfaceEffectGenerator surfaceGen(maskColor, caf::PO_NONE);
        cvf::ref<cvf::Effect>       eff = surfaceGen.generateCachedEffect();
        containmentMaskPart->setEffect(eff.p());

        return containmentMaskPart;
    }

    return nullptr;
}
Exemplo n.º 5
0
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::Part> RivWellFracturePartMgr::createEllipseSurfacePart(const RimEclipseView& activeView)
{
    auto displayCoordTransform = activeView.displayCoordTransform();
    if (displayCoordTransform.isNull()) return nullptr;

    if (m_rimFracture)
    {
        std::vector<cvf::uint>  triangleIndices;
        std::vector<cvf::Vec3f> nodeDisplayCoords;

        {
            std::vector<cvf::Vec3f> nodeCoords;
            m_rimFracture->fractureTemplate()->fractureTriangleGeometry(&nodeCoords, &triangleIndices);

            cvf::Mat4d fractureXf = m_rimFracture->transformMatrix();
            nodeDisplayCoords     = transformToFractureDisplayCoords(nodeCoords, fractureXf, *displayCoordTransform);
        }

        if (triangleIndices.empty() || nodeDisplayCoords.empty())
        {
            return nullptr;
        }

        cvf::ref<cvf::DrawableGeo> geo = buildDrawableGeoFromTriangles(triangleIndices, nodeDisplayCoords);
        CVF_ASSERT(geo.notNull());

        cvf::ref<cvf::Part> surfacePart = new cvf::Part(0, "FractureSurfacePart_ellipse");
        surfacePart->setDrawable(geo.p());
        surfacePart->setSourceInfo(new RivObjectSourceInfo(m_rimFracture));

        cvf::Color4f fractureColor = cvf::Color4f(activeView.fractureColors()->defaultColor());

        RimRegularLegendConfig* legendConfig = nullptr;
        if (activeView.fractureColors() && activeView.fractureColors()->isChecked())
        {
            legendConfig = activeView.fractureColors()->activeLegend();
        }

        if (legendConfig && legendConfig->scalarMapper())
        {
            cvf::Color3ub resultColor = cvf::Color3ub(RiaColorTables::undefinedCellColor());

            if (activeView.fractureColors()->uiResultName() == RiaDefines::conductivityResultName())
            {
                RimEllipseFractureTemplate* ellipseFractureTemplate =
                    dynamic_cast<RimEllipseFractureTemplate*>(m_rimFracture->fractureTemplate());
                if (ellipseFractureTemplate)
                {
                    double conductivity = ellipseFractureTemplate->conductivity();
                    resultColor         = legendConfig->scalarMapper()->mapToColor(conductivity);
                }
            }

            fractureColor.set(cvf::Color3f::fromByteColor(resultColor.r(), resultColor.g(), resultColor.b()));
        }

        caf::SurfaceEffectGenerator surfaceGen(fractureColor, caf::PO_1);
        cvf::ref<cvf::Effect>       eff = surfaceGen.generateCachedEffect();
        surfacePart->setEffect(eff.p());

        return surfacePart;
    }

    return nullptr;
}
Exemplo n.º 6
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RivWellPathPartMgr::buildWellPathParts(cvf::Vec3d displayModelOffset, double characteristicCellSize, cvf::BoundingBox boundingBox)
{
    if (m_wellPathCollection.isNull()) return;

    RigWellPath* wellPathGeometry = m_rimWellPath->wellPathGeometry();
    if (!wellPathGeometry) return;

    if (wellPathGeometry->m_wellPathPoints.size() < 2) return;

    m_wellBranches.clear();
    double wellPathRadius = m_wellPathCollection->wellPathRadiusScaleFactor() * m_rimWellPath->wellPathRadiusScaleFactor() * characteristicCellSize;

//     cvf::Vec3d firstPoint = wellPathGeometry->m_wellPathPoints[0];
//     firstPoint -= displayModelOffset;
//     firstPoint.transformPoint(m_scaleTransform->worldTransform());
//     printf("Well path start pos = (%f, %f, %f)\n", firstPoint.x(), firstPoint.y(), firstPoint.z());
    cvf::Vec3d textPosition = wellPathGeometry->m_wellPathPoints[0];

    // Generate well path as pipe structure
    {
        m_wellBranches.push_back(RivPipeBranchData());
        RivPipeBranchData& pbd = m_wellBranches.back();

        pbd.m_pipeGeomGenerator = new RivPipeGeometryGenerator;

        pbd.m_pipeGeomGenerator->setRadius(wellPathRadius);
        pbd.m_pipeGeomGenerator->setCrossSectionVertexCount(m_wellPathCollection->wellPathCrossSectionVertexCount());
        pbd.m_pipeGeomGenerator->setPipeColor( m_rimWellPath->wellPathColor());

        cvf::ref<cvf::Vec3dArray> cvfCoords = new cvf::Vec3dArray;
        if (m_wellPathCollection->wellPathClip)
        {
            std::vector<cvf::Vec3d> clippedPoints;
            for (size_t idx = 0; idx < wellPathGeometry->m_wellPathPoints.size(); idx++)
            {
                cvf::Vec3d point = wellPathGeometry->m_wellPathPoints[idx];
                if (point.z() < (boundingBox.max().z() + m_wellPathCollection->wellPathClipZDistance))
                    clippedPoints.push_back(point);
            }
            if (clippedPoints.size() < 2) return;

            textPosition = clippedPoints[0];
            cvfCoords->assign(clippedPoints);
        }
        else
        {
            cvfCoords->assign(wellPathGeometry->m_wellPathPoints);
        }
        
        // Scale the centerline coordinates using the Z-scale transform of the grid and correct for the display offset.
        for (size_t cIdx = 0; cIdx < cvfCoords->size(); ++cIdx)
        {
            cvf::Vec4d transfCoord = m_scaleTransform->worldTransform() * cvf::Vec4d((*cvfCoords)[cIdx] - displayModelOffset, 1);
            (*cvfCoords)[cIdx][0] = transfCoord[0];
            (*cvfCoords)[cIdx][1] = transfCoord[1];
            (*cvfCoords)[cIdx][2] = transfCoord[2];
        }

        pbd.m_pipeGeomGenerator->setPipeCenterCoords(cvfCoords.p());
        pbd.m_surfaceDrawable = pbd.m_pipeGeomGenerator->createPipeSurface();
        pbd.m_centerLineDrawable = pbd.m_pipeGeomGenerator->createCenterLine();

        if (pbd.m_surfaceDrawable.notNull())
        {
            pbd.m_surfacePart = new cvf::Part;
            pbd.m_surfacePart->setDrawable(pbd.m_surfaceDrawable.p());
            //printf("Well Path triangleCount = %i (%i points in well path)\n", pbd.m_surfaceDrawable->triangleCount(), wellPathGeometry->m_wellPathPoints.size());

            caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(m_rimWellPath->wellPathColor()), true);
            cvf::ref<cvf::Effect> eff = surfaceGen.generateEffect();

            pbd.m_surfacePart->setEffect(eff.p());
        }

        if (pbd.m_centerLineDrawable.notNull())
        {
            pbd.m_centerLinePart = new cvf::Part;
            pbd.m_centerLinePart->setDrawable(pbd.m_centerLineDrawable.p());
            //printf("Well Path vertexCount = %i\n", pbd.m_centerLineDrawable->vertexCount());

            caf::MeshEffectGenerator gen(m_rimWellPath->wellPathColor());
            cvf::ref<cvf::Effect> eff = gen.generateEffect();

            pbd.m_centerLinePart->setEffect(eff.p());
        }
    }

    // Generate label with well path name
    textPosition -= displayModelOffset;
    textPosition.transformPoint(m_scaleTransform->worldTransform());
    textPosition.z() += characteristicCellSize; // * m_rimReservoirView->wellCollection()->wellHeadScaleFactor();
    textPosition.z() += 1.2 * characteristicCellSize;

    m_wellLabelPart = NULL;
    if (m_wellPathCollection->showWellPathLabel() && m_rimWellPath->showWellPathLabel())
    {
        cvf::Font* standardFont = RiaApplication::instance()->standardFont();

        cvf::ref<cvf::DrawableText> drawableText = new cvf::DrawableText;
        drawableText->setFont(standardFont);
        drawableText->setCheckPosVisible(false);
        drawableText->setDrawBorder(false);
        drawableText->setDrawBackground(false);
        drawableText->setVerticalAlignment(cvf::TextDrawer::CENTER);
        //drawableText->setTextColor(cvf::Color3f(0.08f, 0.08f, 0.08f));
        drawableText->setTextColor(cvf::Color3f(0.92f, 0.92f, 0.92f));

        cvf::String cvfString = cvfqt::Utils::fromQString(m_rimWellPath->name());

        cvf::Vec3f textCoord(textPosition);
        drawableText->addText(cvfString, textCoord);

        cvf::ref<cvf::Part> part = new cvf::Part;
        part->setName("RivWellHeadPartMgr: text " + cvfString);
        part->setDrawable(drawableText.p());

        cvf::ref<cvf::Effect> eff = new cvf::Effect;

        part->setEffect(eff.p());
        part->setPriority(1000);

        m_wellLabelPart = part;
    }

    m_needsTransformUpdate = false;
}
Exemplo n.º 7
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RivWellHeadPartMgr::buildWellHeadParts(size_t frameIndex)
{
    m_wellHeadParts.clear();

    if (m_rimReservoirView.isNull()) return;

    RigCaseData* rigReservoir = m_rimReservoirView->eclipseCase()->reservoirData();

    RimEclipseWell* well = m_rimWell;

    RigSingleWellResultsData* wellResults = well->wellResults();

    if (wellResults->m_staticWellCells.m_wellResultBranches.size() == 0)
    {
        wellResults->computeStaticWellCellPath();
    }
    if (wellResults->m_staticWellCells.m_wellResultBranches.size() == 0) return;

    if (!wellResults->hasWellResult(frameIndex)) return;

    const RigWellResultFrame& wellResultFrame = wellResults->wellResultFrame(frameIndex);

    const RigCell& whCell = rigReservoir->cellFromWellResultCell(wellResultFrame.m_wellHead);

    double characteristicCellSize = rigReservoir->mainGrid()->characteristicIJCellSize();

    // Match this position with pipe start position in RivWellPipesPartMgr::calculateWellPipeCenterline()
    cvf::Vec3d whStartPos = whCell.faceCenter(cvf::StructGridInterface::NEG_K);
    whStartPos -= rigReservoir->mainGrid()->displayModelOffset();
    whStartPos.transformPoint(m_scaleTransform->worldTransform());

    // Compute well head based on the z position of the top of the K column the well head is part of
    cvf::Vec3d whEndPos = whStartPos;

    if (m_rimReservoirView->wellCollection()->wellHeadPosition() == RimEclipseWellCollection::WELLHEAD_POS_TOP_COLUMN)
    {
        // Position well head at top active cell of IJ-column

        size_t i, j, k;
        rigReservoir->mainGrid()->ijkFromCellIndex(whCell.mainGridCellIndex(), &i, &j, &k);

        size_t kIndexWellHeadCell = k;
        k = 0;
        
        size_t topActiveCellIndex = rigReservoir->mainGrid()->cellIndexFromIJK(i, j, k);
        while(k < kIndexWellHeadCell && !m_rimReservoirView->currentActiveCellInfo()->isActive(topActiveCellIndex))
        {
            k++;
            topActiveCellIndex = rigReservoir->mainGrid()->cellIndexFromIJK(i, j, k);
        }
        
        const RigCell& topActiveCell = rigReservoir->mainGrid()->cell(topActiveCellIndex);
        cvf::Vec3d topCellPos = topActiveCell.faceCenter(cvf::StructGridInterface::NEG_K);
        topCellPos -= rigReservoir->mainGrid()->displayModelOffset();
        topCellPos.transformPoint(m_scaleTransform->worldTransform());

        // Modify position if top active cell is closer to sea than well head
        if (kIndexWellHeadCell > k)
        {
            whEndPos.z() = topCellPos.z() + characteristicCellSize;
        }
    }
    else
    {
        // Position well head at top of active cells bounding box

        cvf::Vec3d activeCellsBoundingBoxMax = m_rimReservoirView->currentActiveCellInfo()->geometryBoundingBox().max();
        activeCellsBoundingBoxMax -= rigReservoir->mainGrid()->displayModelOffset();
        activeCellsBoundingBoxMax.transformPoint(m_scaleTransform->worldTransform());

        whEndPos.z() = activeCellsBoundingBoxMax.z();
    }

    cvf::Vec3d arrowPosition = whEndPos;
    arrowPosition.z() += 2.0;

    // Well head pipe geometry
    {
        cvf::ref<cvf::Vec3dArray> wellHeadPipeCoords = new cvf::Vec3dArray;
        wellHeadPipeCoords->resize(2);
        wellHeadPipeCoords->set(0, whStartPos);
        wellHeadPipeCoords->set(1, whEndPos);

        cvf::ref<RivPipeGeometryGenerator> pipeGeomGenerator = new RivPipeGeometryGenerator;
        pipeGeomGenerator->setPipeCenterCoords(wellHeadPipeCoords.p());
        pipeGeomGenerator->setPipeColor(well->wellPipeColor());
        pipeGeomGenerator->setCrossSectionVertexCount(m_rimReservoirView->wellCollection()->pipeCrossSectionVertexCount());

        double pipeRadius = m_rimReservoirView->wellCollection()->pipeRadiusScaleFactor() * m_rimWell->pipeRadiusScaleFactor() * characteristicCellSize;
        pipeGeomGenerator->setRadius(pipeRadius);

        cvf::ref<cvf::DrawableGeo> pipeSurface = pipeGeomGenerator->createPipeSurface();
        cvf::ref<cvf::DrawableGeo> centerLineDrawable = pipeGeomGenerator->createCenterLine();

        if (pipeSurface.notNull())
        {
            cvf::ref<cvf::Part> part = new cvf::Part;
            part->setName("RivWellHeadPartMgr: surface " + cvfqt::Utils::toString(well->name()));
            part->setDrawable(pipeSurface.p());

            caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(well->wellPipeColor()), caf::PO_1);
            cvf::ref<cvf::Effect> eff = surfaceGen.generateEffect();

            part->setEffect(eff.p());

            m_wellHeadParts.push_back(part.p());
        }

        if (centerLineDrawable.notNull())
        {
            cvf::ref<cvf::Part> part = new cvf::Part;
            part->setName("RivWellHeadPartMgr: centerline " + cvfqt::Utils::toString(well->name()));
            part->setDrawable(centerLineDrawable.p());

            caf::MeshEffectGenerator meshGen(well->wellPipeColor());
            cvf::ref<cvf::Effect> eff = meshGen.generateEffect();

            part->setEffect(eff.p());

            m_wellHeadParts.push_back(part.p());
        }
    }

    double arrowLength = characteristicCellSize * m_rimReservoirView->wellCollection()->wellHeadScaleFactor();
    cvf::Vec3d textPosition = arrowPosition;
    textPosition.z() += 1.2 * arrowLength;
    
    cvf::Mat4f matr;
    if (wellResultFrame.m_productionType != RigWellResultFrame::PRODUCER)
    {
        matr = cvf::Mat4f::fromRotation(cvf::Vec3f(1.0f, 0.0f, 0.0f), cvf::Math::toRadians(180.0f));
    }

    double ijScaleFactor = arrowLength / 6;
    matr(0, 0) *= ijScaleFactor;
    matr(1, 1) *= ijScaleFactor;
    matr(2, 2) *= arrowLength;

    if (wellResultFrame.m_productionType != RigWellResultFrame::PRODUCER)
    {
        arrowPosition.z() += arrowLength;
    }

    matr.setTranslation(cvf::Vec3f(arrowPosition));

    cvf::GeometryBuilderFaceList builder;
    cvf::ArrowGenerator gen;
    gen.setShaftRelativeRadius(0.5f);
    gen.setHeadRelativeRadius(1.0f);
    gen.setHeadRelativeLength(0.4f);
    gen.setNumSlices(m_rimReservoirView->wellCollection()->pipeCrossSectionVertexCount());
    gen.generate(&builder);

    cvf::ref<cvf::Vec3fArray> vertices = builder.vertices();
    cvf::ref<cvf::UIntArray> faceList = builder.faceList();

    size_t i;
    for (i = 0; i < vertices->size(); i++)
    {
        cvf::Vec3f v = vertices->get(i);
        v.transformPoint(matr);
        vertices->set(i, v);
    }

    cvf::ref<cvf::DrawableGeo> geo1 = new cvf::DrawableGeo;
    geo1->setVertexArray(vertices.p());   
    geo1->setFromFaceList(*faceList);
    geo1->computeNormals();


    {
        cvf::ref<cvf::Part> part = new cvf::Part;
        part->setName("RivWellHeadPartMgr: arrow " + cvfqt::Utils::toString(well->name()));
        part->setDrawable(geo1.p());

        cvf::Color4f headColor(cvf::Color3::GRAY);
        if (wellResultFrame.m_isOpen)
        {
            if (wellResultFrame.m_productionType == RigWellResultFrame::PRODUCER)
            {
                headColor = cvf::Color4f(cvf::Color3::GREEN);
            }
            else if (wellResultFrame.m_productionType == RigWellResultFrame::OIL_INJECTOR)
            {
                headColor = cvf::Color4f(cvf::Color3::ORANGE);
            }
            else if (wellResultFrame.m_productionType == RigWellResultFrame::GAS_INJECTOR)
            {
                headColor = cvf::Color4f(cvf::Color3::RED);
            }
            else if (wellResultFrame.m_productionType == RigWellResultFrame::WATER_INJECTOR)
            {
                headColor = cvf::Color4f(cvf::Color3::BLUE);
            }
        }

        caf::SurfaceEffectGenerator surfaceGen(headColor, caf::PO_1);
        cvf::ref<cvf::Effect> eff = surfaceGen.generateEffect();

        part->setEffect(eff.p());
        m_wellHeadParts.push_back(part.p());
    }

    if (m_rimReservoirView->wellCollection()->showWellLabel() && well->showWellLabel() && !well->name().isEmpty())
    {
        cvf::Font* standardFont = RiaApplication::instance()->standardFont();

        cvf::ref<cvf::DrawableText> drawableText = new cvf::DrawableText;
        drawableText->setFont(standardFont);
        drawableText->setCheckPosVisible(false);
        drawableText->setDrawBorder(false);
        drawableText->setDrawBackground(false);
        drawableText->setVerticalAlignment(cvf::TextDrawer::CENTER);
        drawableText->setTextColor(m_rimReservoirView->wellCollection()->wellLabelColor());

        cvf::String cvfString = cvfqt::Utils::toString(well->name());

        cvf::Vec3f textCoord(textPosition);
        drawableText->addText(cvfString, textCoord);

        cvf::ref<cvf::Part> part = new cvf::Part;
        part->setName("RivWellHeadPartMgr: text " + cvfString);
        part->setDrawable(drawableText.p());

        cvf::ref<cvf::Effect> eff = new cvf::Effect;

        part->setEffect(eff.p());
        part->setPriority(11);

        m_wellHeadParts.push_back(part.p());
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void CellEdgeEffectGenerator::updateForFixedFunctionRendering(cvf::Effect* effect) const
{
    caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(cvf::Color3f::CRIMSON), caf::PO_1);

    surfaceGen.updateEffect(effect);
}
Exemplo n.º 9
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RivWellPipesPartMgr::buildWellPipeParts()
{
    if (m_rimReservoirView.isNull()) return;

    m_wellBranches.clear();

    m_pipeBranchesCLCoords.clear();
    std::vector< std::vector <RigWellResultPoint> > pipeBranchesCellIds;

    RigSimulationWellCenterLineCalculator::calculateWellPipeCenterline(m_rimWell.p(), m_pipeBranchesCLCoords, pipeBranchesCellIds);

    double characteristicCellSize = m_rimReservoirView->eclipseCase()->reservoirData()->mainGrid()->characteristicIJCellSize();
    double pipeRadius = m_rimReservoirView->wellCollection()->pipeRadiusScaleFactor() *m_rimWell->pipeRadiusScaleFactor() * characteristicCellSize;

    cvf::ref<RivEclipseWellSourceInfo> sourceInfo = new RivEclipseWellSourceInfo(m_rimWell);

    for (size_t brIdx = 0; brIdx < pipeBranchesCellIds.size(); ++brIdx)
    {
        m_wellBranches.push_back(RivPipeBranchData());
        RivPipeBranchData& pbd = m_wellBranches.back();

        pbd.m_cellIds = pipeBranchesCellIds[brIdx];

        pbd.m_pipeGeomGenerator = new RivPipeGeometryGenerator;

        pbd.m_pipeGeomGenerator->setRadius(pipeRadius);
        pbd.m_pipeGeomGenerator->setCrossSectionVertexCount(m_rimReservoirView->wellCollection()->pipeCrossSectionVertexCount());
        pbd.m_pipeGeomGenerator->setPipeColor( m_rimWell->wellPipeColor());

        cvf::ref<cvf::Vec3dArray> cvfCoords = new cvf::Vec3dArray;
        cvfCoords->assign(m_pipeBranchesCLCoords[brIdx]);
        
        // Scale the centerline coordinates using the Z-scale transform of the grid and correct for the display offset.
        const RigMainGrid* mainGrid = m_rimReservoirView->eclipseCase()->reservoirData()->mainGrid();

        for (size_t cIdx = 0; cIdx < cvfCoords->size(); ++cIdx)
        {
            cvf::Vec4d transfCoord = m_scaleTransform->worldTransform()* cvf::Vec4d((*cvfCoords)[cIdx] - mainGrid->displayModelOffset(), 1);
            (*cvfCoords)[cIdx][0] = transfCoord[0];
            (*cvfCoords)[cIdx][1] = transfCoord[1];
            (*cvfCoords)[cIdx][2] = transfCoord[2];
        }

        pbd.m_pipeGeomGenerator->setPipeCenterCoords(cvfCoords.p());
        pbd.m_surfaceDrawable = pbd.m_pipeGeomGenerator->createPipeSurface();
        pbd.m_centerLineDrawable = pbd.m_pipeGeomGenerator->createCenterLine();

        if (pbd.m_surfaceDrawable.notNull())
        {
            pbd.m_surfacePart = new cvf::Part;
            pbd.m_surfacePart->setDrawable(pbd.m_surfaceDrawable.p());

            caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(m_rimWell->wellPipeColor()), caf::PO_1);
            cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();

            pbd.m_surfacePart->setEffect(eff.p());
            
            pbd.m_surfacePart->setSourceInfo(sourceInfo.p());
        }

        if (pbd.m_centerLineDrawable.notNull())
        {
            pbd.m_centerLinePart = new cvf::Part;
            pbd.m_centerLinePart->setDrawable(pbd.m_centerLineDrawable.p());

            caf::MeshEffectGenerator gen(m_rimWell->wellPipeColor());
            cvf::ref<cvf::Effect> eff = gen.generateCachedEffect();

            pbd.m_centerLinePart->setEffect(eff.p());
        }
    }

    m_needsTransformUpdate = false;
}
Exemplo n.º 10
0
//--------------------------------------------------------------------------------------------------
/// The pipe geometry needs to be rebuilt on scale change to keep the pipes round
//--------------------------------------------------------------------------------------------------
void RivWellPathPartMgr::buildWellPathParts(cvf::Vec3d displayModelOffset, double characteristicCellSize, 
                                            cvf::BoundingBox wellPathClipBoundingBox)
{
    RimWellPathCollection* wellPathCollection = NULL;
    m_rimWellPath->firstAncestorOrThisOfType(wellPathCollection);
    if (!wellPathCollection) return;

    RigWellPath* wellPathGeometry = m_rimWellPath->wellPathGeometry();
    if (!wellPathGeometry) return;

    if (wellPathGeometry->m_wellPathPoints.size() < 2) return;

    clearAllBranchData();
    double wellPathRadius = wellPathCollection->wellPathRadiusScaleFactor() * m_rimWellPath->wellPathRadiusScaleFactor() * characteristicCellSize;

    cvf::Vec3d textPosition = wellPathGeometry->m_wellPathPoints[0];

    // Generate the well path geometry as a line and pipe structure
    {
        RivPipeBranchData& pbd = m_pipeBranchData;

        pbd.m_pipeGeomGenerator = new RivPipeGeometryGenerator;

        pbd.m_pipeGeomGenerator->setRadius(wellPathRadius);
        pbd.m_pipeGeomGenerator->setCrossSectionVertexCount(wellPathCollection->wellPathCrossSectionVertexCount());
        pbd.m_pipeGeomGenerator->setPipeColor( m_rimWellPath->wellPathColor());

        cvf::ref<cvf::Vec3dArray> cvfCoords = new cvf::Vec3dArray;
        if (wellPathCollection->wellPathClip)
        {
            size_t firstVisibleSegmentIndex = cvf::UNDEFINED_SIZE_T;
            for (size_t idx = 0; idx < wellPathGeometry->m_wellPathPoints.size(); idx++)
            {
                cvf::Vec3d point = wellPathGeometry->m_wellPathPoints[idx];
                if (point.z() < (wellPathClipBoundingBox.max().z() + wellPathCollection->wellPathClipZDistance))
                {
                    firstVisibleSegmentIndex = idx;
                    break;
                }
            }

            std::vector<cvf::Vec3d> clippedPoints;

            if (firstVisibleSegmentIndex != cvf::UNDEFINED_SIZE_T)
            {
                for (size_t idx = firstVisibleSegmentIndex; idx < wellPathGeometry->m_wellPathPoints.size(); idx++)
                {
                    clippedPoints.push_back(wellPathGeometry->m_wellPathPoints[idx]);
                }

                pbd.m_pipeGeomGenerator->setFirstSegmentIndex(firstVisibleSegmentIndex);
            }

            if (clippedPoints.size() < 2) return;

            textPosition = clippedPoints[0];
            cvfCoords->assign(clippedPoints);
        }
        else
        {
            cvfCoords->assign(wellPathGeometry->m_wellPathPoints);
        }
        
        // Scale the centerline coordinates using the Z-scale transform of the grid and correct for the display offset.
        for (size_t cIdx = 0; cIdx < cvfCoords->size(); ++cIdx)
        {
            cvf::Vec4d transfCoord = m_scaleTransform->worldTransform() * cvf::Vec4d((*cvfCoords)[cIdx] - displayModelOffset, 1);
            (*cvfCoords)[cIdx][0] = transfCoord[0];
            (*cvfCoords)[cIdx][1] = transfCoord[1];
            (*cvfCoords)[cIdx][2] = transfCoord[2];
        }

        pbd.m_pipeGeomGenerator->setPipeCenterCoords(cvfCoords.p());
        pbd.m_surfaceDrawable = pbd.m_pipeGeomGenerator->createPipeSurface();
        pbd.m_centerLineDrawable = pbd.m_pipeGeomGenerator->createCenterLine();

        if (pbd.m_surfaceDrawable.notNull())
        {
            pbd.m_surfacePart = new cvf::Part;
            pbd.m_surfacePart->setDrawable(pbd.m_surfaceDrawable.p());
            
            RivWellPathSourceInfo* sourceInfo = new RivWellPathSourceInfo(m_rimWellPath);
            pbd.m_surfacePart->setSourceInfo(sourceInfo);

            caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(m_rimWellPath->wellPathColor()), caf::PO_1);
            cvf::ref<cvf::Effect> eff = surfaceGen.generateCachedEffect();

            pbd.m_surfacePart->setEffect(eff.p());
        }

        if (pbd.m_centerLineDrawable.notNull())
        {
            pbd.m_centerLinePart = new cvf::Part;
            pbd.m_centerLinePart->setDrawable(pbd.m_centerLineDrawable.p());

            caf::MeshEffectGenerator gen(m_rimWellPath->wellPathColor());
            cvf::ref<cvf::Effect> eff = gen.generateCachedEffect();

            pbd.m_centerLinePart->setEffect(eff.p());
        }
    }

    // Generate label with well-path name

    textPosition -= displayModelOffset;
    textPosition.transformPoint(m_scaleTransform->worldTransform());
    textPosition.z() += characteristicCellSize; // * m_rimReservoirView->wellCollection()->wellHeadScaleFactor();
    textPosition.z() += 1.2 * characteristicCellSize;

    m_wellLabelPart = NULL;
    if (wellPathCollection->showWellPathLabel() && m_rimWellPath->showWellPathLabel() && !m_rimWellPath->name().isEmpty())
    {
        cvf::Font* font = RiaApplication::instance()->customFont();

        cvf::ref<cvf::DrawableText> drawableText = new cvf::DrawableText;
        drawableText->setFont(font);
        drawableText->setCheckPosVisible(false);
        drawableText->setDrawBorder(false);
        drawableText->setDrawBackground(false);
        drawableText->setVerticalAlignment(cvf::TextDrawer::CENTER);
        drawableText->setTextColor(wellPathCollection->wellPathLabelColor());

        cvf::String cvfString = cvfqt::Utils::toString(m_rimWellPath->name());

        cvf::Vec3f textCoord(textPosition);
        drawableText->addText(cvfString, textCoord);

        cvf::ref<cvf::Part> part = new cvf::Part;
        part->setName("RivWellHeadPartMgr: text " + cvfString);
        part->setDrawable(drawableText.p());

        cvf::ref<cvf::Effect> eff = new cvf::Effect;

        part->setEffect(eff.p());
        part->setPriority(1000);

        m_wellLabelPart = part;
    }

    m_needsTransformUpdate = false;
}