//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void AABBTree::leafBoundingBox(cvf::BoundingBox& bb, size_t iStartIdx, size_t iEndIdx) const
{
    CVF_ASSERT(iStartIdx <= iEndIdx);

    bb.reset();

    size_t i;
    for (i = iStartIdx; i <= iEndIdx; i++)
    {
        CVF_ASSERT(m_ppLeaves[i]);
        bb.add(m_ppLeaves[i]->boundingBox());
    }
}
//--------------------------------------------------------------------------------------------------
/// Find all indices to all bounding boxes intersecting the given bounding box and add them to indices
//--------------------------------------------------------------------------------------------------
void BoundingBoxTreeImpl::findIntersections(const cvf::BoundingBox& bb, std::vector<size_t>& indices) const
{
    if (bb.isValid())
    {
        findIntersections(bb, m_pRoot, indices);
    }
}
Example #3
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
bool RigWellPath::isAnyPointInsideBoundingBox(const std::vector<cvf::Vec3d>& points, const cvf::BoundingBox& boundingBox)
{
    for (const cvf::Vec3d& point : points)
    {
        if (boundingBox.contains(point)) return true;
    }

    return false;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void BoundingBoxTreeImpl::findIntersections(const cvf::BoundingBox& bb, const AABBTreeNode* node, std::vector<size_t>& cvIndices) const
{
    CVF_TIGHT_ASSERT(bb.isValid());
    
    if (node && bb.intersects(node->boundingBox()))
    {
        if (node->type() == AB_LEAF)
        {
            const AABBTreeNodeLeaf* leaf = static_cast<const AABBTreeNodeLeaf*>(node);
            {
                cvIndices.push_back(leaf->index());
                return;
            }
        }
        else if (node->type() == AB_INTERNAL)
        {
            const AABBTreeNodeInternal* internalNode = static_cast<const AABBTreeNodeInternal*>(node);

            findIntersections(bb, internalNode->left(), cvIndices);
            findIntersections(bb, internalNode->right(), cvIndices);
        }
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RivGridBoxGenerator::setGridBoxDomainCoordBoundingBox(const cvf::BoundingBox& bb)
{
    cvf::BoundingBox expandedBB;
    {
        double expandFactor = 0.05;

        cvf::Vec3d expandedMin;
        expandedMin.x() = bb.min().x() - bb.extent().x() * expandFactor;
        expandedMin.y() = bb.min().y() - bb.extent().y() * expandFactor;
        expandedMin.z() = bb.min().z() - bb.extent().z() * expandFactor;

        cvf::Vec3d expandedMax;
        expandedMax.x() = bb.max().x() + bb.extent().x() * expandFactor;
        expandedMax.y() = bb.max().y() + bb.extent().y() * expandFactor;
        expandedMax.z() = bb.max().z() + bb.extent().z() * expandFactor;

        expandedBB.add(expandedMin);
        expandedBB.add(expandedMax);
    }

    m_domainCoordsBoundingBox = expandedBB;

    m_domainCoordsXValues.clear();
    m_domainCoordsYValues.clear();
    m_domainCoordsZValues.clear();

    cvf::Vec3d min = m_domainCoordsBoundingBox.min();
    cvf::Vec3d max = m_domainCoordsBoundingBox.max();

    cvf::ScalarMapperDiscreteLinear m_linDiscreteScalarMapper;
    size_t levelCount = 6;

    m_linDiscreteScalarMapper.setRange(min.x(), max.x());
    m_linDiscreteScalarMapper.setLevelCount(levelCount, true);
    m_linDiscreteScalarMapper.majorTickValues(&m_domainCoordsXValues);

    m_linDiscreteScalarMapper.setRange(min.y(), max.y());
    m_linDiscreteScalarMapper.setLevelCount(levelCount, true);
    m_linDiscreteScalarMapper.majorTickValues(&m_domainCoordsYValues);

    m_linDiscreteScalarMapper.setRange(min.z(), max.z());
    m_linDiscreteScalarMapper.setLevelCount(levelCount, true);
    m_linDiscreteScalarMapper.majorTickValues(&m_domainCoordsZValues);
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
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 RivGridBoxGenerator::setGridBoxDomainCoordBoundingBox(const cvf::BoundingBox& bb)
{
    double expandFactor = 0.05;
    
    // Use ScalarMapperDiscreteLinear to find human readable tick mark positions for grid box sub division coordinate values
    // Expand the range for ScalarMapperDiscreteLinear until the geometry bounding box has a generated tick mark coords
    // both below minimum and above maximum bounding box coords

    cvf::Vec3d min = bb.min();
    cvf::Vec3d max = bb.max();

    size_t levelCount = 6;

    {
        bool majorTickValuesCoversDomainValues = false;
        while (!majorTickValuesCoversDomainValues)
        {
            m_domainCoordsXValues.clear();

            cvf::ScalarMapperDiscreteLinear linDiscreteScalarMapper;
            linDiscreteScalarMapper.setRange(min.x(), max.x());
            linDiscreteScalarMapper.setLevelCount(levelCount, true);
            linDiscreteScalarMapper.majorTickValues(&m_domainCoordsXValues);

            majorTickValuesCoversDomainValues = true;

            if (m_domainCoordsXValues[1] > bb.min().x())
            {
                min.x() = min.x() - bb.extent().x() * expandFactor;
                max.x() = max.x() + bb.extent().x() * expandFactor;
                majorTickValuesCoversDomainValues = false;
            }

            if (m_domainCoordsXValues[m_domainCoordsXValues.size() - 1] < bb.max().x())
            {
                min.x() = min.x() - bb.extent().x() * expandFactor;
                max.x() = max.x() + bb.extent().x() * expandFactor;
                majorTickValuesCoversDomainValues = false;
            }
        }
    }

    {
        bool majorTickValuesCoversDomainValues = false;
        while (!majorTickValuesCoversDomainValues)
        {
            m_domainCoordsYValues.clear();

            cvf::ScalarMapperDiscreteLinear linDiscreteScalarMapper;
            linDiscreteScalarMapper.setRange(min.y(), max.y());
            linDiscreteScalarMapper.setLevelCount(levelCount, true);
            linDiscreteScalarMapper.majorTickValues(&m_domainCoordsYValues);

            majorTickValuesCoversDomainValues = true;

            if (m_domainCoordsYValues[1] > bb.min().y())
            {
                min.y() = min.y() - bb.extent().y() * expandFactor;
                max.y() = max.y() + bb.extent().y() * expandFactor;
                majorTickValuesCoversDomainValues = false;
            }

            if (m_domainCoordsYValues[m_domainCoordsYValues.size() - 1] < bb.max().y())
            {
                min.y() = min.y() - bb.extent().y() * expandFactor;
                max.y() = max.y() + bb.extent().y() * expandFactor;
                majorTickValuesCoversDomainValues = false;
            }
        }
    }

    {
        bool majorTickValuesCoversDomainValues = false;
        while (!majorTickValuesCoversDomainValues)
        {
            m_domainCoordsZValues.clear();

            cvf::ScalarMapperDiscreteLinear linDiscreteScalarMapper;
            linDiscreteScalarMapper.setRange(min.z(), max.z());
            linDiscreteScalarMapper.setLevelCount(levelCount, true);
            linDiscreteScalarMapper.majorTickValues(&m_domainCoordsZValues);

            majorTickValuesCoversDomainValues = true;

            if (m_domainCoordsZValues[1] > bb.min().z())
            {
                min.z() = min.z() - bb.extent().z() * expandFactor;
                max.z() = max.z() + bb.extent().z() * expandFactor;
                majorTickValuesCoversDomainValues = false;
            }

            if (m_domainCoordsZValues[m_domainCoordsZValues.size() - 1] < bb.max().z())
            {
                min.z() = min.z() - bb.extent().z() * expandFactor;
                max.z() = max.z() + bb.extent().z() * expandFactor;
                majorTickValuesCoversDomainValues = false;
            }
        }
    }
    
    cvf::BoundingBox expandedBB;
    expandedBB.add(min);
    expandedBB.add(max);

    m_domainCoordsBoundingBox = expandedBB;
}
//--------------------------------------------------------------------------------------------------
/// 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;
}