File indexing completed on 2024-06-09 04:18:33
0001 /* 0002 * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 0003 * 0004 * This file is part of the KD Chart library. 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "KChartTernaryLineDiagram.h" 0010 #include "KChartTernaryLineDiagram_p.h" 0011 0012 #include <limits> 0013 0014 #include <QPainter> 0015 0016 #include <KChartPaintContext.h> 0017 0018 #include "KChartLineAttributes.h" 0019 #include "KChartDataValueAttributes.h" 0020 #include "KChartMarkerAttributes.h" 0021 #include "TernaryPoint.h" 0022 #include "TernaryConstants.h" 0023 #include "KChartPainterSaver_p.h" 0024 0025 using namespace KChart; 0026 0027 #define d d_func() 0028 0029 TernaryLineDiagram::Private::Private() 0030 : AbstractTernaryDiagram::Private() 0031 { 0032 } 0033 0034 TernaryLineDiagram::TernaryLineDiagram ( QWidget* parent, 0035 TernaryCoordinatePlane* plane ) 0036 : AbstractTernaryDiagram( new Private(), parent, plane ) 0037 { 0038 init(); 0039 setDatasetDimensionInternal( 3 ); // the third column is implicit 0040 0041 DataValueAttributes dataValueAttributes; 0042 dataValueAttributes.setVisible( true ); 0043 MarkerAttributes markerAttributes; 0044 markerAttributes.setMarkerStyle( MarkerAttributes::MarkerCircle ); 0045 markerAttributes.setVisible( true ); 0046 dataValueAttributes.setMarkerAttributes( markerAttributes ); 0047 attributesModel()->setDefaultForRole( 0048 KChart::DataValueLabelAttributesRole, 0049 QVariant::fromValue( dataValueAttributes ) ); 0050 } 0051 0052 TernaryLineDiagram::~TernaryLineDiagram() 0053 { 0054 } 0055 0056 void TernaryLineDiagram::init() 0057 { 0058 } 0059 0060 void TernaryLineDiagram::resize (const QSizeF& area) 0061 { 0062 AbstractTernaryDiagram::resize( area ); 0063 } 0064 0065 void TernaryLineDiagram::paint (PaintContext *paintContext) 0066 { 0067 d->reverseMapper.clear(); 0068 0069 d->paint( paintContext ); 0070 // sanity checks: 0071 if ( model() == nullptr ) return; 0072 0073 QPainter* p = paintContext->painter(); 0074 PainterSaver s( p ); 0075 0076 TernaryCoordinatePlane* plane = 0077 (TernaryCoordinatePlane*) paintContext->coordinatePlane(); 0078 Q_ASSERT( plane ); 0079 0080 qreal x, y, z; 0081 0082 // for some reason(?) TernaryPointDiagram is using per-diagram DVAs only: 0083 const DataValueAttributes attrs( dataValueAttributes() ); 0084 0085 d->forgetAlreadyPaintedDataValues(); 0086 0087 int columnCount = model()->columnCount( rootIndex() ); 0088 QPointF start; 0089 for (int column=0; column<columnCount; column+=datasetDimension() ) 0090 { 0091 int numrows = model()->rowCount( rootIndex() ); 0092 for ( int row = 0; row < numrows; row++ ) 0093 { 0094 // see if there is data otherwise skip 0095 QModelIndex base = model()->index( row, column ); // checked 0096 if ( ! model()->data( base ).isNull() ) 0097 { 0098 p->setPen( PrintingParameters::scalePen( pen( base ) ) ); 0099 p->setBrush( brush( base ) ); 0100 0101 // retrieve data 0102 x = qMax<qreal>( model()->data( model()->index( row, column, rootIndex() ) ).toReal(), // checked 0103 0.0 ); 0104 y = qMax<qreal>( model()->data( model()->index( row, column+1, rootIndex() ) ).toReal(), // checked 0105 0.0 ); 0106 z = qMax<qreal>( model()->data( model()->index( row, column+2, rootIndex() ) ).toReal(), // checked 0107 0.0 ); 0108 0109 qreal total = x + y + z; 0110 if ( fabs( total ) > 3 * std::numeric_limits<qreal>::epsilon() ) { 0111 TernaryPoint tPunkt( x / total, y / total ); 0112 QPointF diagramLocation = translate( tPunkt ); 0113 QPointF widgetLocation = plane->translate( diagramLocation ); 0114 0115 if ( row > 0 ) { 0116 p->drawLine( start, widgetLocation ); 0117 } 0118 paintMarker( p, model()->index( row, column, rootIndex() ), widgetLocation ); // checked 0119 start = widgetLocation; 0120 // retrieve text and data value attributes 0121 // FIXME use data model DisplayRole text 0122 QString text = tr( "(%1, %2, %3)", "(x, y, z) values of the data point" ) 0123 .arg( x * 100, 0, 'f', 0 ) 0124 .arg( y * 100, 0, 'f', 0 ) 0125 .arg( z * 100, 0, 'f', 0 ); 0126 d->paintDataValueText( p, attrs, widgetLocation, true, text, true ); 0127 } else { 0128 // ignore and do not paint this point, garbage data 0129 qDebug() << "TernaryPointDiagram::paint: data point x/y/z:" 0130 << x << "/" << y << "/" << z << "ignored, unusable."; 0131 } 0132 } 0133 } 0134 } 0135 } 0136 0137 const QPair< QPointF, QPointF > TernaryLineDiagram::calculateDataBoundaries () const 0138 { 0139 // this is a constant, because we defined it to be one: 0140 static QPair<QPointF, QPointF> Boundaries( 0141 TriangleBottomLeft, 0142 QPointF( TriangleBottomRight.x(), TriangleHeight ) ); 0143 return Boundaries; 0144 }