File indexing completed on 2024-12-15 04:02:36
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 "KChartTernaryPointDiagram.h" 0010 #include "KChartTernaryPointDiagram_p.h" 0011 0012 #include <limits> 0013 0014 #include <QPainter> 0015 0016 #include <KChartPaintContext.h> 0017 0018 #include "TernaryPoint.h" 0019 #include "TernaryConstants.h" 0020 0021 using namespace KChart; 0022 0023 #define d d_func() 0024 0025 TernaryPointDiagram::Private::Private() 0026 : AbstractTernaryDiagram::Private() 0027 { 0028 } 0029 0030 TernaryPointDiagram::TernaryPointDiagram ( QWidget* parent, 0031 TernaryCoordinatePlane* plane ) 0032 : AbstractTernaryDiagram( new Private(), parent, plane ) 0033 { 0034 init(); 0035 setDatasetDimensionInternal( 3 ); // the third column is implicit 0036 } 0037 0038 TernaryPointDiagram::~TernaryPointDiagram() 0039 { 0040 } 0041 0042 void TernaryPointDiagram::init() 0043 { 0044 d->reverseMapper.setDiagram( this ); 0045 } 0046 0047 void TernaryPointDiagram::resize (const QSizeF& area) 0048 { 0049 AbstractTernaryDiagram::resize( area ); 0050 } 0051 0052 void TernaryPointDiagram::paint (PaintContext *paintContext) 0053 { 0054 d->reverseMapper.clear(); 0055 0056 d->paint( paintContext ); 0057 0058 // sanity checks: 0059 if ( model() == nullptr ) return; 0060 0061 QPainter* p = paintContext->painter(); 0062 PainterSaver s( p ); 0063 0064 TernaryCoordinatePlane* plane = 0065 static_cast< TernaryCoordinatePlane* >( paintContext->coordinatePlane() ); 0066 Q_ASSERT( plane ); 0067 0068 qreal x, y, z; 0069 0070 0071 // for some reason(?) TernaryPointDiagram is using per-diagram DVAs only: 0072 const DataValueAttributes attrs( dataValueAttributes() ); 0073 0074 d->forgetAlreadyPaintedDataValues(); 0075 0076 int columnCount = model()->columnCount( rootIndex() ); 0077 for (int column=0; column<columnCount; column+=datasetDimension() ) 0078 { 0079 int numrows = model()->rowCount( rootIndex() ); 0080 for ( int row = 0; row < numrows; row++ ) 0081 { 0082 QModelIndex base = model()->index( row, column, rootIndex() ); // checked 0083 // see if there is data otherwise skip 0084 if ( ! model()->data( base ).isNull() ) 0085 { 0086 p->setPen( PrintingParameters::scalePen( pen( base ) ) ); 0087 p->setBrush( brush( base ) ); 0088 0089 // retrieve data 0090 x = qMax<qreal>( model()->data( model()->index( row, column+0, rootIndex() ) ).toReal(), // checked 0091 0.0 ); 0092 y = qMax<qreal>( model()->data( model()->index( row, column+1, rootIndex() ) ).toReal(), // checked 0093 0.0 ); 0094 z = qMax<qreal>( model()->data( model()->index( row, column+2, rootIndex() ) ).toReal(), // checked 0095 0.0 ); 0096 0097 // fix messed up data values (paint as much as possible) 0098 qreal total = x + y + z; 0099 if ( fabs( total ) > 3 * std::numeric_limits<qreal>::epsilon() ) { 0100 TernaryPoint tPunkt( x / total, y / total ); 0101 QPointF diagramLocation = translate( tPunkt ); 0102 QPointF widgetLocation = plane->translate( diagramLocation ); 0103 0104 paintMarker( p, model()->index( row, column, rootIndex() ), widgetLocation ); // checked 0105 QString text = tr( "(%1, %2, %3)", "(x, y, z) values of the data point" ) 0106 .arg( x * 100, 0, 'f', 0 ) 0107 .arg( y * 100, 0, 'f', 0 ) 0108 .arg( z * 100, 0, 'f', 0 ); 0109 d->paintDataValueText( p, attrs, widgetLocation, true, text, true ); 0110 } else { 0111 // ignore and do not paint this point, garbage data 0112 qDebug() << "TernaryPointDiagram::paint: data point x/y/z:" 0113 << x << "/" << y << "/" << z << "ignored, unusable."; 0114 } 0115 } 0116 } 0117 } 0118 } 0119 0120 const QPair< QPointF, QPointF > TernaryPointDiagram::calculateDataBoundaries () const 0121 { 0122 // this is a constant, because we defined it to be one: 0123 static QPair<QPointF, QPointF> Boundaries( 0124 TriangleBottomLeft, 0125 QPointF( TriangleBottomRight.x(), TriangleHeight ) ); 0126 return Boundaries; 0127 } 0128