//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::appendFracturePerforationLengthParts(const RimEclipseView& activeView, cvf::ModelBasicList* model)
{
    if (!m_rimFracture->isChecked()) return;

    if (!m_rimFracture->fractureTemplate()) return;
    if (m_rimFracture->fractureTemplate()->orientationType() != RimFractureTemplate::ALONG_WELL_PATH) return;

    auto displayCoordTransform = activeView.displayCoordTransform();
    if (displayCoordTransform.isNull()) return;

    double characteristicCellSize = activeView.ownerCase()->characteristicCellSize();
    double wellPathRadius         = 1.0;

    {
        RimWellPath* rimWellPath = nullptr;
        m_rimFracture->firstAncestorOrThisOfType(rimWellPath);
        if (rimWellPath)
        {
            wellPathRadius = rimWellPath->wellPathRadius(characteristicCellSize);
        }
    }

    {
        RimSimWellInView* simWell = nullptr;
        m_rimFracture->firstAncestorOrThisOfType(simWell);
        if (simWell)
        {
            wellPathRadius = simWell->pipeRadius();
        }
    }

    std::vector<cvf::Vec3d> displayCoords =
        displayCoordTransform->transformToDisplayCoords(m_rimFracture->perforationLengthCenterLineCoords());

    if (!displayCoords.empty())
    {
        cvf::ref<RivObjectSourceInfo> objectSourceInfo  = new RivObjectSourceInfo(m_rimFracture);
        double                        perforationRadius = wellPathRadius * 1.2;
        cvf::Collection<cvf::Part>    parts;

        RivPipeGeometryGenerator geoGenerator;
        geoGenerator.cylinderWithCenterLineParts(
            &parts, displayCoords, RiaColorTables::wellPathComponentColors()[RiaDefines::PERFORATION_INTERVAL], perforationRadius);

        for (auto part : parts)
        {
            part->setSourceInfo(objectSourceInfo.p());
            model->addPart(part.p());
        }
    }
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellFracturePartMgr::appendGeometryPartsToModel(cvf::ModelBasicList* model, const RimEclipseView& eclView)
{
    if (!m_rimFracture->isChecked() || !eclView.fractureColors()->isChecked()) return;

    if (!m_rimFracture->fractureTemplate()) return;

    m_visibleFracturePolygons.clear();

    double characteristicCellSize = eclView.ownerCase()->characteristicCellSize();

    cvf::Collection<cvf::Part>   parts;
    RimStimPlanFractureTemplate* stimPlanFracTemplate =
        dynamic_cast<RimStimPlanFractureTemplate*>(m_rimFracture->fractureTemplate());

    if (stimPlanFracTemplate)
    {
        if (eclView.fractureColors()->stimPlanResultColorType() == RimStimPlanColors::SINGLE_ELEMENT_COLOR)
        {
            auto part = createStimPlanElementColorSurfacePart(eclView);
            if (part.notNull()) parts.push_back(part.p());
        }
        else
        {
            auto part = createStimPlanColorInterpolatedSurfacePart(eclView);
            if (part.notNull()) parts.push_back(part.p());
        }

        if (eclView.fractureColors()->showStimPlanMesh())
        {
            auto part = createStimPlanMeshPart(eclView);
            if (part.notNull()) parts.push_back(part.p());
        }
    }
    else
    {
        auto part = createEllipseSurfacePart(eclView);
        if (part.notNull()) parts.push_back(part.p());
    }

    double distanceToCenterLine = 1.0;
    {
        RimWellPathCollection* wellPathColl = nullptr;
        m_rimFracture->firstAncestorOrThisOfType(wellPathColl);
        if (wellPathColl)
        {
            distanceToCenterLine = wellPathColl->wellPathRadiusScaleFactor() * characteristicCellSize;
        }

        RimSimWellInView* simWell = nullptr;
        m_rimFracture->firstAncestorOrThisOfType(simWell);
        if (simWell)
        {
            distanceToCenterLine = simWell->pipeRadius();
        }
    }

    // Make sure the distance is slightly smaller than the pipe radius to make the pipe is visible through the fracture
    distanceToCenterLine *= 0.1;

    if (distanceToCenterLine < 0.03)
    {
        distanceToCenterLine = 0.03;
    }

    auto fractureMatrix = m_rimFracture->transformMatrix();

    if (m_rimFracture->fractureTemplate() &&
        m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH)
    {
        cvf::Vec3d partTranslation = distanceToCenterLine * cvf::Vec3d(fractureMatrix.col(2));

        for (auto& part : parts)
        {
            RivWellFracturePartMgr::addPartAtPositiveAndNegativeTranslation(model, part.p(), partTranslation);
        }
    }
    else
    {
        for (auto& part : parts)
        {
            model->addPart(part.p());
        }
    }

    if (m_rimFracture->fractureTemplate())
    {
        // Position the containment mask outside the fracture parts
        // Always duplicate the containment mask parts

        {
            auto maskOfFractureAreasOutsideGrid = createMaskOfFractureOutsideGrid(eclView);
            if (maskOfFractureAreasOutsideGrid.notNull())
            {
                double scaleFactor = 0.03;
                if (m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH)
                {
                    scaleFactor = 2 * distanceToCenterLine;
                }

                cvf::Vec3d partTranslation = scaleFactor * cvf::Vec3d(fractureMatrix.col(2));

                RivWellFracturePartMgr::addPartAtPositiveAndNegativeTranslation(
                    model, maskOfFractureAreasOutsideGrid.p(), partTranslation);
            }
        }

        if (m_rimFracture->fractureTemplate()->fractureContainment()->isEnabled())
        {
            // Position the containment mask outside the fracture parts
            // Always duplicate the containment mask parts

            auto containmentMask = createContainmentMaskPart(eclView);
            if (containmentMask.notNull())
            {
                double scaleFactor = 0.03;
                if (m_rimFracture->fractureTemplate() &&
                    m_rimFracture->fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH)
                {
                    scaleFactor = 2 * distanceToCenterLine;
                }

                cvf::Vec3d partTranslation = scaleFactor * cvf::Vec3d(fractureMatrix.col(2));

                RivWellFracturePartMgr::addPartAtPositiveAndNegativeTranslation(model, containmentMask.p(), partTranslation);
            }
        }
    }

    appendFracturePerforationLengthParts(eclView, model);
}