//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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()); } }
//-------------------------------------------------------------------------------------------------- /// 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; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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; }
//-------------------------------------------------------------------------------------------------- /// 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; }