///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017- Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RiuPlotAnnotationTool.h" #include "RimPlotAxisAnnotation.h" #include "RiuGuiTheme.h" #include "cafCategoryMapper.h" #include "cvfMath.h" #include "qwt_plot.h" #include "qwt_plot_zoneitem.h" #include "qwt_text.h" #include #include //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuPlotAnnotationTool::~RiuPlotAnnotationTool() { detachAllAnnotations(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPlotAnnotationTool::attachNamedRegions( QwtPlot* plot, const std::vector& names, RiaDefines::Orientation depthOrientation, const std::vector>& regionRanges, RiaDefines::RegionDisplay regionDisplay, const caf::ColorTable& colorTable, int shadingAlphaByte, bool showNames /*= true */, RiaDefines::TrackSpan trackSpan /*= FULL_WIDTH*/, const std::vector& brushStyles /* = {}*/, int fontSize ) { if ( names.size() != regionRanges.size() ) return; m_plot = plot; double delta = 0.5; std::vector categoryIndices( names.size() ); std::iota( categoryIndices.begin(), categoryIndices.end(), 0 ); caf::CategoryMapper catMapper; catMapper.setCategories( categoryIndices ); catMapper.setInterpolateColors( colorTable.color3ubArray() ); RiaDefines::Orientation annotationOrientation = RiaDefines::Orientation::HORIZONTAL; if ( depthOrientation == RiaDefines::Orientation::HORIZONTAL ) annotationOrientation = RiaDefines::Orientation::VERTICAL; for ( size_t i = 0; i < names.size(); i++ ) { auto* line( new QwtPlotMarker() ); QString name; if ( showNames && !names[i].isEmpty() ) { name = names[i]; if ( ( regionDisplay & RiaDefines::COLOR_SHADING ) == 0 && names[i].toLower().indexOf( "top" ) == -1 ) { name += " Top"; } } if ( regionDisplay & RiaDefines::COLOR_SHADING ) { cvf::Color3ub cvfColor = catMapper.mapToColor( static_cast( i ) ); QColor shadingColor( cvfColor.r(), cvfColor.g(), cvfColor.b(), shadingAlphaByte ); auto* shading = new QwtPlotZoneItem(); if ( depthOrientation == RiaDefines::Orientation::HORIZONTAL ) shading->setOrientation( Qt::Vertical ); else shading->setOrientation( Qt::Horizontal ); shading->setInterval( regionRanges[i].first, regionRanges[i].second ); shading->setPen( shadingColor, 0.0, Qt::NoPen ); QBrush brush( shadingColor ); if ( i < brushStyles.size() ) { brush.setStyle( brushStyles[i] ); } shading->setBrush( brush ); shading->attach( m_plot ); shading->setZ( -100.0 ); shading->setXAxis( QwtAxis::XTop ); m_plotItems.push_back( shading ); } QColor lineColor( 0, 0, 0, 0 ); QColor textColor( 0, 0, 0, 255 ); if ( regionDisplay & RiaDefines::DARK_LINES || regionDisplay & RiaDefines::COLORED_LINES || regionDisplay & RiaDefines::LIGHT_LINES ) { cvf::Color3ub cvfColor = catMapper.mapToColor( static_cast( i ) ); QColor cycledColor( cvfColor.r(), cvfColor.g(), cvfColor.b() ); if ( regionDisplay & RiaDefines::DARK_LINES ) { lineColor = QColor( 50, 50, 100 ); } else if ( regionDisplay & RiaDefines::LIGHT_LINES ) { lineColor = QColor( 200, 200, 200 ); } else { lineColor = cycledColor; } textColor = lineColor; } Qt::Alignment horizontalAlignment = trackTextAlignment( trackSpan ); RiuPlotAnnotationTool::setLineProperties( line, name, annotationOrientation, regionRanges[i].first, Qt::DashLine, lineColor, textColor, horizontalAlignment, fontSize ); line->attach( m_plot ); m_plotItems.push_back( line ); if ( ( i != names.size() - 1 ) && cvf::Math::abs( regionRanges[i].second - regionRanges[i + 1].first ) > delta ) { auto* bottomLine( new QwtPlotMarker() ); RiuPlotAnnotationTool::setLineProperties( bottomLine, QString(), annotationOrientation, regionRanges[i].second, Qt::DashLine, lineColor, textColor, Qt::AlignRight, fontSize ); bottomLine->attach( m_plot ); m_plotItems.push_back( bottomLine ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPlotAnnotationTool::attachWellPicks( QwtPlot* plot, const std::vector& names, const std::vector& yPositions ) { detachAllAnnotations(); if ( names.size() != yPositions.size() ) return; m_plot = plot; for ( size_t i = 0; i < names.size(); i++ ) { auto* line( new QwtPlotMarker() ); RiuPlotAnnotationTool::setLineProperties( line, names[i], RiaDefines::Orientation::HORIZONTAL, yPositions[i] ); line->attach( m_plot ); m_plotItems.push_back( line ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPlotAnnotationTool::attachAnnotationLine( QwtPlot* plot, const QColor& color, const QString& annotationText, Qt::PenStyle penStyle, const double position, RiaDefines::Orientation orientation ) { m_plot = plot; auto* line( new QwtPlotMarker() ); auto textColor = color; if ( orientation == RiaDefines::Orientation::VERTICAL ) { textColor = RiuGuiTheme::getColorByVariableName( "textColor" ); } RiuPlotAnnotationTool::setLineProperties( line, annotationText, orientation, position, penStyle, color, textColor ); m_plotItems.push_back( line ); line->attach( m_plot ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPlotAnnotationTool::attachAnnotation( QwtPlot* plot, RimPlotAxisAnnotation* annotation, RiaDefines::Orientation orientation ) { if ( annotation->annotationType() == RimPlotAxisAnnotation::AnnotationType::LINE ) { attachAnnotationLine( plot, annotation->color(), annotation->name(), annotation->penStyle(), annotation->value(), orientation ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPlotAnnotationTool::attachAnnotationRange( QwtPlot* plot, const QColor& color, const QString& annotationText, const double rangeStart, const double rangeEnd, RiaDefines::Orientation orientation ) { m_plot = plot; if ( orientation == RiaDefines::Orientation::HORIZONTAL ) { RiuPlotAnnotationTool::horizontalRange( annotationText, std::make_pair( rangeStart, rangeEnd ), color, RiuGuiTheme::getColorByVariableName( "textColor" ) ); } else if ( orientation == RiaDefines::Orientation::VERTICAL ) { RiuPlotAnnotationTool::verticalRange( annotationText, std::make_pair( rangeStart, rangeEnd ), color, RiuGuiTheme::getColorByVariableName( "textColor" ), Qt::AlignHCenter ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPlotAnnotationTool::detachAllAnnotations() { if ( m_plot ) { for ( auto& plotItem : m_plotItems ) { plotItem->detach(); delete plotItem; } } m_plotItems.clear(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- Qt::Alignment RiuPlotAnnotationTool::trackTextAlignment( RiaDefines::TrackSpan trackSpan ) { switch ( trackSpan ) { case RiaDefines::TrackSpan::FULL_WIDTH: return Qt::AlignRight; case RiaDefines::TrackSpan::LEFT_COLUMN: return Qt::AlignLeft; case RiaDefines::TrackSpan::CENTRE_COLUMN: return Qt::AlignCenter; case RiaDefines::TrackSpan::RIGHT_COLUMN: return Qt::AlignRight; } return Qt::AlignRight; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPlotAnnotationTool::horizontalRange( const QString& name, const std::pair yRange, const QColor& color /*= QColor( 0, 0, 100 )*/, const QColor& textColor /*= QColor( 0, 0, 100 )*/, Qt::Alignment horizontalAlignment /*= Qt::AlignRight */ ) { QColor shadingColor = color; shadingColor.setAlpha( 10 ); auto* shading = new QwtPlotZoneItem(); shading->setOrientation( Qt::Horizontal ); shading->setInterval( yRange.first, yRange.second ); shading->setPen( shadingColor, 0.0, Qt::NoPen ); QBrush brush( shadingColor ); shading->setBrush( brush ); shading->attach( m_plot ); shading->setZ( -100.0 ); shading->setXAxis( QwtAxis::XBottom ); m_plotItems.push_back( shading ); auto* line( new QwtPlotMarker() ); RiuPlotAnnotationTool::setLineProperties( line, name, RiaDefines::Orientation::HORIZONTAL, yRange.first, Qt::DashLine, color, color, horizontalAlignment ); line->attach( m_plot ); m_plotItems.push_back( line ); auto* bottomLine( new QwtPlotMarker() ); RiuPlotAnnotationTool::setLineProperties( bottomLine, QString(), RiaDefines::Orientation::HORIZONTAL, yRange.second, Qt::DashLine, color, color ); bottomLine->attach( m_plot ); m_plotItems.push_back( bottomLine ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPlotAnnotationTool::verticalRange( const QString& name, const std::pair xRange, const QColor& color /*= QColor( 0, 0, 100 )*/, const QColor& textColor /*= QColor( 0, 0, 100 )*/, Qt::Alignment horizontalAlignment /*= Qt::AlignRight */ ) { QColor shadingColor = color; shadingColor.setAlpha( 50 ); auto* shading = new QwtPlotZoneItem(); shading->setOrientation( Qt::Vertical ); shading->setInterval( xRange.first, xRange.second ); shading->setPen( shadingColor, 0.0, Qt::NoPen ); QBrush brush( shadingColor ); shading->setBrush( brush ); shading->attach( m_plot ); shading->setZ( -100.0 ); shading->setXAxis( QwtAxis::XBottom ); m_plotItems.push_back( shading ); QStringList labels = name.split( " - " ); auto* line( new QwtPlotMarker() ); RiuPlotAnnotationTool::setLineProperties( line, labels[0], RiaDefines::Orientation::VERTICAL, xRange.first, Qt::SolidLine, color, textColor, Qt::AlignRight | horizontalAlignment ); line->attach( m_plot ); m_plotItems.push_back( line ); auto* rightLine( new QwtPlotMarker() ); RiuPlotAnnotationTool::setLineProperties( rightLine, labels.size() == 2 ? labels[1] : QString(), RiaDefines::Orientation::VERTICAL, xRange.second, Qt::SolidLine, color, textColor, Qt::AlignLeft | horizontalAlignment ); rightLine->attach( m_plot ); m_plotItems.push_back( rightLine ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPlotAnnotationTool::setLineProperties( QwtPlotMarker* line, const QString& name, RiaDefines::Orientation orientation, double linePosition, Qt::PenStyle lineStyle, const QColor& color /*= QColor( 0, 0, 100 )*/, const QColor& textColor /*= QColor( 0, 0, 100 )*/, Qt::Alignment horizontalAlignment /*= Qt::AlignRight*/, int fontSize /*= 0 */ ) { QPen curvePen; curvePen.setStyle( lineStyle ); curvePen.setColor( color ); curvePen.setWidth( 1 ); line->setLinePen( curvePen ); QwtText label( name ); label.setColor( textColor ); if ( fontSize > 0 ) label.setFont( QFont( label.font().key(), fontSize ) ); line->setLabel( label ); line->setLabelAlignment( horizontalAlignment | Qt::AlignBottom ); if ( orientation == RiaDefines::Orientation::HORIZONTAL ) { line->setLineStyle( QwtPlotMarker::HLine ); line->setYValue( linePosition ); } else { line->setLineStyle( QwtPlotMarker::VLine ); line->setXValue( linePosition ); } }