Add lib/libkdchart

This commit is contained in:
2012-02-11 14:34:29 +01:00
parent 67e00fcaa1
commit 9e1686bd6e
278 changed files with 221 additions and 13 deletions

View File

@@ -0,0 +1,79 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "KDChartAbstractTernaryDiagram.h"
#include "KDChartAbstractTernaryDiagram_p.h"
#include "KDChartTernaryCoordinatePlane.h"
using namespace KDChart;
AbstractTernaryDiagram::Private::Private()
: AbstractDiagram::Private()
{
}
void AbstractTernaryDiagram::init()
{
}
#define d d_func()
AbstractTernaryDiagram::AbstractTernaryDiagram( QWidget* parent,
TernaryCoordinatePlane* plane )
: AbstractDiagram( parent, plane )
{
}
AbstractTernaryDiagram::~AbstractTernaryDiagram()
{
while ( ! d->axesList.isEmpty() ) {
TernaryAxis* axis = d->axesList.takeFirst();
delete axis;
}
}
void AbstractTernaryDiagram::addAxis( TernaryAxis* axis )
{
d->axesList.append( axis );
// FIXME update
}
void AbstractTernaryDiagram::takeAxis( TernaryAxis* axis )
{
int index = d->axesList.indexOf( axis );
if ( index != -1 )
d->axesList.removeAt( index );
// FIXME update
}
TernaryAxisList AbstractTernaryDiagram::axes() const
{
return d->axesList;
}
void AbstractTernaryDiagram::paint (PaintContext *paintContext)
{
d->paint( paintContext );
}

View File

@@ -0,0 +1,63 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTABSTRACTTERNARYDIAGRAM_H
#define KDCHARTABSTRACTTERNARYDIAGRAM_H
#include "../KDChartAbstractDiagram.h"
#include "KDChartTernaryAxis.h"
namespace KDChart {
class TernaryCoordinatePlane;
class TernaryAxis;
/**
* @brief Base class for diagrams based on a ternary coordinate plane.
*/
class KDCHART_EXPORT AbstractTernaryDiagram : public AbstractDiagram
{
Q_OBJECT
Q_DISABLE_COPY( AbstractTernaryDiagram )
KDCHART_DECLARE_DERIVED_DIAGRAM( AbstractTernaryDiagram,
TernaryCoordinatePlane )
public:
explicit AbstractTernaryDiagram ( QWidget* parent = 0,
TernaryCoordinatePlane* plane = 0 );
virtual ~AbstractTernaryDiagram();
virtual void resize (const QSizeF &area) = 0;
virtual void paint (PaintContext *paintContext);
virtual void addAxis( TernaryAxis* axis );
virtual void takeAxis( TernaryAxis* axis );
virtual TernaryAxisList axes () const;
protected:
virtual const QPair< QPointF, QPointF > calculateDataBoundaries () const = 0;
};
}
#endif

View File

@@ -0,0 +1,120 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTABSTRACTTERNARYDIAGRAM_P_H
#define KDCHARTABSTRACTTERNARYDIAGRAM_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the KD Chart API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "KDChartAbstractTernaryDiagram.h"
#include "KDChartTernaryCoordinatePlane.h"
#include <KDChartAbstractDiagram_p.h>
#include <KDChartAbstractThreeDAttributes.h>
#include <KDChartGridAttributes.h>
#include "../Scenery/ReverseMapper.h"
#include "../Scenery/ChartGraphicsItem.h"
#include <KDABLibFakes>
namespace KDChart {
class CartesianCoordinatePlane;
class AbstractTernaryDiagram;
/**
* \internal
*/
class AbstractTernaryDiagram::Private : public AbstractDiagram::Private
{
friend class AbstractTernaryDiagram;
public:
Private();
~Private() {}
Private( const Private& rhs ) :
AbstractDiagram::Private( rhs ),
// Do not copy axes and reference diagrams.
axesList(),
referenceDiagram( 0 )
{
}
TernaryAxisList axesList;
AbstractTernaryDiagram* referenceDiagram;
QPointF referenceDiagramOffset;
void drawPoint( QPainter* p, int row, int column,
const QPointF& widgetLocation )
{
// Q_ASSERT( false ); // unused, to be removed
static const double Diameter = 5.0;
static const double Radius = Diameter / 2.0;
QRectF ellipseRect( widgetLocation - QPointF( Radius, Radius ),
QSizeF( Diameter, Diameter ) );
p->drawEllipse( ellipseRect );
reverseMapper.addRect( row, column, ellipseRect );
}
virtual void paint( PaintContext* paintContext )
{
paintContext->painter()->setRenderHint( QPainter::Antialiasing,
antiAliasing );
if ( !axesList.isEmpty() ) {
Q_FOREACH( TernaryAxis* axis, axesList ) {
PainterSaver s( paintContext->painter() );
axis->paintCtx( paintContext );
}
}
}
};
KDCHART_IMPL_DERIVED_DIAGRAM( AbstractTernaryDiagram, AbstractDiagram, TernaryCoordinatePlane )
/*
inline AbstractTernaryDiagram::AbstractTernaryDiagram( Private * p )
: AbstractDiagram( p ) { init(); }
inline AbstractTernaryDiagram::AbstractTernaryDiagram(
Private * p, QWidget* parent, CartesianCoordinatePlane* plane )
: AbstractDiagram( p, parent, plane ) { init(); }
inline AbstractTernaryDiagram::Private * AbstractTernaryDiagram::d_func()
{ return static_cast<Private*>( AbstractDiagram::d_func() ); }
inline const AbstractTernaryDiagram::Private * AbstractTernaryDiagram::d_func() const
{ return static_cast<const Private*>( AbstractDiagram::d_func() ); }
*/
}
#endif /* KDCHARTABSTRACTTERNARYDIAGRAM_P_H */

View File

@@ -0,0 +1,284 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "KDChartTernaryAxis.h"
#include <QPainter>
#include <KDChartChart>
#include <KDChartPaintContext>
#include "TernaryConstants.h"
#include "KDChartTernaryCoordinatePlane.h"
#include "KDChartAbstractTernaryDiagram.h"
#include "../src/KDChartLayoutItems.h"
#include "PrerenderedElements/KDChartTextLabelCache.h"
using namespace KDChart;
// m_label and m_fifty do not have to be pointers, once the class is
// pimpled (PrerenderedLabel is not published API)
TernaryAxis::TernaryAxis ( AbstractTernaryDiagram* diagram)
: AbstractAxis( diagram )
, m_position( KDChartEnums::PositionUnknown )
, m_label( new PrerenderedLabel )
, m_fifty( new PrerenderedLabel )
{
resetTitleTextAttributes();
setPosition( KDChartEnums::PositionSouth ); // arbitrary
m_fifty->setText( QObject::tr( "50%" ) ); // const
// FIXME is this consistent with other diagram/axis/plane implementations?
diagram->addAxis( this );
}
TernaryAxis::~TernaryAxis()
{
delete m_label; m_label = 0;
delete m_label; m_fifty = 0;
}
void TernaryAxis::paintAll (QPainter &)
{
// not used
}
void TernaryAxis::paint (QPainter *)
{
// not used
}
void TernaryAxis::paintCtx (PaintContext * paintContext)
{
QPainter* p = paintContext->painter();
TernaryCoordinatePlane* plane =
(TernaryCoordinatePlane*) paintContext->coordinatePlane();
// QObject* refArea = plane->parent();
QRectF drawArea = paintContext->rectangle();
QRectF titleArea;
// paint the axis label (across the triangle, that one):
QList<PrerenderedLabel*> labels;
labels << m_label << m_fifty;
Q_FOREACH( PrerenderedLabel* label, labels ) {
const QPixmap& pixmap = label->pixmap();
QPointF point = plane->translate( label->position() )
- label->referencePointLocation();
p->drawPixmap( point, pixmap );
}
}
bool TernaryAxis::isEmpty() const
{
// todo: what's this method for?
return false;
}
QRect TernaryAxis::geometry () const
{
return m_geometry;
}
void TernaryAxis::setGeometry (const QRect &rect)
{
m_geometry = rect;
}
QSize TernaryAxis::minimumSize () const
{
// todo: return realistic sizes
return QSize( 100, 100 );
}
QSize TernaryAxis::maximumSize () const
{
return QSize( 300, 200 );
}
QSize TernaryAxis::sizeHint () const
{
return QSize( 150, 100 );
}
Qt::Orientations TernaryAxis::expandingDirections () const
{
return Qt::Vertical | Qt::Horizontal;
}
const Position TernaryAxis::position () const
{
return m_position;
}
void TernaryAxis::setPosition (Position p)
{
if ( p == position() ) return;
if ( p != KDChartEnums::PositionWest
&& p != KDChartEnums::PositionEast
&& p != KDChartEnums::PositionSouth )
{
qDebug() << "TernaryAxis::setPosition: only south, east and west are supported "
"positions for ternary axes.";
return;
}
if ( m_title.isEmpty() )
switch( p.value() ) {
case KDChartEnums::PositionSouth:
m_label->setText( tr( "A" ) );
break;
case KDChartEnums::PositionWest:
m_label->setText( tr( "C" ) );
break;
case KDChartEnums::PositionEast:
m_label->setText( tr( "B" ) );
break;
default:
break;
}
m_position = p;
updatePrerenderedLabels(); // position has changed
}
void TernaryAxis::setTitleText( const QString& text )
{
m_title = text; // do not remove
m_label->setText( text );
}
QString TernaryAxis::titleText() const
{
return m_label->text();
}
void TernaryAxis::setTitleTextAttributes( const TextAttributes &a )
{
m_titleAttributes = a;
updatePrerenderedLabels();
}
TextAttributes TernaryAxis::titleTextAttributes() const
{
return m_titleAttributes;
}
void TernaryAxis::resetTitleTextAttributes()
{
TextAttributes a;
m_titleAttributes = a;
updatePrerenderedLabels();
}
bool TernaryAxis::hasDefaultTitleTextAttributes() const
{
TextAttributes a;
return m_titleAttributes == a;
}
void TernaryAxis::updatePrerenderedLabels()
{
TextAttributes attributes = titleTextAttributes();
double axisLabelAngle = 0.0;
double fiftyMarkAngle = 0.0;
QPointF axisLabelPosition;
QPointF fiftyMarkPosition;
KDChartEnums::PositionValue fiftyMarkReferencePoint = KDChartEnums::PositionUnknown;
switch( position().value() ) {
case KDChartEnums::PositionSouth:
// this is the axis on the other side of A
axisLabelAngle = 0.0;
fiftyMarkAngle = 0.0;
axisLabelPosition = TriangleTop;
fiftyMarkPosition = 0.5 * AxisVector_B_C - RelMarkerLength * Norm_B_C;
fiftyMarkReferencePoint = KDChartEnums::PositionNorth;
break;
case KDChartEnums::PositionEast:
// this is the axis on the other side of B
axisLabelAngle = 240.0;
fiftyMarkAngle = 60;
axisLabelPosition = TriangleBottomLeft;
fiftyMarkPosition = AxisVector_B_C + 0.5 * AxisVector_C_A - RelMarkerLength * Norm_C_A;
fiftyMarkReferencePoint = KDChartEnums::PositionSouth;
break;
case KDChartEnums::PositionWest:
// this is the axis on the other side of C
axisLabelAngle = 120.0;
fiftyMarkAngle = 300.0;
axisLabelPosition = TriangleBottomRight;
fiftyMarkPosition = 0.5 * AxisVector_B_A + RelMarkerLength * Norm_B_A;
fiftyMarkReferencePoint = KDChartEnums::PositionSouth;
break;
case KDChartEnums::PositionUnknown:
break; // initial value
default:
qDebug() << "TernaryAxis::updatePrerenderedLabel: unknown location";
};
m_label->setFont( attributes.font() );
// m_label->setText( titleText() ); // done by setTitleText()
m_label->setAngle( axisLabelAngle );
m_label->setPosition( axisLabelPosition );
m_label->setReferencePoint( KDChartEnums::PositionSouth );
QFont font = attributes.font();
font.setPointSizeF( 0.85 * font.pointSizeF() );
m_fifty->setFont( font );
m_fifty->setAngle( fiftyMarkAngle );
m_fifty->setPosition( fiftyMarkPosition );
m_fifty->setReferencePoint( fiftyMarkReferencePoint );
}
QPair<QSizeF, QSizeF> TernaryAxis::requiredMargins() const
{
QSizeF topleft( 0.0, 0.0 );
QSizeF bottomRight( 0.0, 0.0 );
switch( position().value() ) {
case KDChartEnums::PositionSouth:
// the label of the south axis is, in fact, up north.
topleft.setHeight( m_label->pixmap().height() );
bottomRight.setHeight( m_fifty->pixmap().height() );
break;
case KDChartEnums::PositionWest:
bottomRight.setWidth( m_label->pixmap().width()
- m_label->referencePointLocation().x() );
bottomRight.setHeight( m_label->pixmap().height()
- m_label->referencePointLocation().y() );
break;
case KDChartEnums::PositionEast:
topleft.setWidth( m_label->pixmap().width()
- ( m_label->pixmap().width()
- m_label->referencePointLocation().x() ) );
bottomRight.setHeight( m_label->pixmap().height()
- ( m_label->pixmap().height()
- m_label->referencePointLocation().y() ) );
break;
default:
qDebug() << "TernaryAxis::requiredMargins: unknown location";
}
// qDebug() << "TernaryAxis::requiredMargins:" << topleft << bottomRight;
return QPair<QSizeF, QSizeF>( topleft, bottomRight );
}

View File

@@ -0,0 +1,96 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTTERNARYAXIS_H
#define KDCHARTTERNARYAXIS_H
#include <KDChartAbstractAxis>
#include <KDChartPosition>
#include <KDChartTextAttributes>
class PrerenderedLabel;
namespace KDChart {
class AbstractTernaryDiagram;
/**
* The class for ternary axes
*/
class KDCHART_EXPORT TernaryAxis : public AbstractAxis
{
Q_OBJECT
Q_DISABLE_COPY( TernaryAxis )
KDCHART_DECLARE_PRIVATE_DERIVED_PARENT( TernaryAxis, AbstractDiagram* )
public:
explicit TernaryAxis ( AbstractTernaryDiagram* diagram = 0 );
~TernaryAxis();
virtual void paintAll( QPainter &);
virtual void paint (QPainter *);
virtual void paintCtx (PaintContext *);
virtual QRect geometry () const;
virtual void setGeometry (const QRect &rect);
virtual bool isEmpty () const;
virtual QSize minimumSize () const;
virtual QSize maximumSize () const;
virtual QSize sizeHint () const;
virtual Qt::Orientations expandingDirections () const ;
virtual const Position position () const;
virtual void setPosition (Position p);
void setTitleText( const QString& text );
QString titleText() const;
void setTitleTextAttributes( const TextAttributes &a );
TextAttributes titleTextAttributes() const;
void resetTitleTextAttributes();
bool hasDefaultTitleTextAttributes() const;
QPair<QSizeF, QSizeF> requiredMargins() const;
private:
void updatePrerenderedLabels();
// TODO, move class variables to private class
QRect m_geometry;
Position m_position;
QString m_title;
TextAttributes m_titleAttributes;
// FIXME (Mirko): Move axis labels from grid to here, do not
// expose them, just paint them. Use title text for text. Make
// a function to allow the coordinate plane to calculate the
// necessary margins, like this:
PrerenderedLabel* m_label;
PrerenderedLabel* m_fifty;
};
typedef QList<TernaryAxis*> TernaryAxisList;
}
#endif

View File

@@ -0,0 +1,205 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "KDChartTernaryCoordinatePlane.h"
#include "KDChartTernaryCoordinatePlane_p.h"
#include <QtDebug>
#include <QPainter>
#include "KDChartPaintContext.h"
#include "KDChartPainterSaver_p.h"
#include "KDChartTernaryAxis.h"
#include "KDChartAbstractTernaryDiagram.h"
#include "TernaryConstants.h"
using namespace KDChart;
#define d d_func()
TernaryCoordinatePlane::Private::Private()
: AbstractCoordinatePlane::Private()
{
}
TernaryCoordinatePlane::TernaryCoordinatePlane( Chart* parent )
: AbstractCoordinatePlane( new Private(), parent )
{
}
TernaryCoordinatePlane::~TernaryCoordinatePlane()
{
}
void TernaryCoordinatePlane::init()
{
}
void TernaryCoordinatePlane::addDiagram( AbstractDiagram* diagram )
{
Q_ASSERT_X ( dynamic_cast<AbstractTernaryDiagram*>( diagram ),
"TernaryCoordinatePlane::addDiagram", "Only ternary "
"diagrams can be added to a ternary coordinate plane!" );
AbstractCoordinatePlane::addDiagram ( diagram );
// connect ( diagram, SIGNAL ( layoutChanged ( AbstractDiagram* ) ),
// SLOT ( slotLayoutChanged ( AbstractDiagram* ) ) );
// connect( diagram, SIGNAL( propertiesChanged() ),this, SIGNAL( propertiesChanged() ) );
}
void TernaryCoordinatePlane::layoutDiagrams()
{ // this is our "resize event":
// all diagrams always take the same space, nothing to be done here
// the "inner" margin (adjustments to diagram coordinates)
QRectF diagramNativeRectangle ( QPointF( 0.0, 0.0 ),
QSizeF( TriangleWidth, TriangleHeight ) );
QPair<QSizeF, QSizeF> margins = grid()->requiredMargins();
d->diagramRect = areaGeometry();
diagramNativeRectangle.adjust
(-margins.first.width(), -margins.first.height(),
margins.second.width(), margins.second.height() );
// the "outer" margin (distance between diagram contents and area,
// determined by axis label overlap
{
QSizeF topleft( 0.0, 0.0 );
QSizeF bottomRight( 0.0, 0.0 );
Q_FOREACH( AbstractDiagram* abstractDiagram, diagrams() ) {
AbstractTernaryDiagram* diagram =
qobject_cast<AbstractTernaryDiagram*>( abstractDiagram );
Q_ASSERT( diagram );
Q_FOREACH( TernaryAxis* axis, diagram->axes() ) {
QPair<QSizeF, QSizeF> margin = axis->requiredMargins();
topleft = topleft.expandedTo( margin.first );
bottomRight = bottomRight.expandedTo( margin.second );
}
}
d->diagramRectContainer =
d->diagramRect.adjusted( topleft.width(),
topleft.height(),
-bottomRight.width(),
-bottomRight.height() );
}
// now calculate isometric projection, x and y widget coordinate
// units, and location of (0.0, 0.0) in diagram coordinates
QPointF zeroZeroPoint = d->diagramRectContainer.bottomLeft();
double w = d->diagramRectContainer.width();
double h = d->diagramRectContainer.height();
double usableWidth;
double usableHeight;
if ( TriangleHeight * w > h ) {
// shorten width:
usableWidth = h / diagramNativeRectangle.height();
usableHeight = h;
zeroZeroPoint.setX( zeroZeroPoint.x() + ( w - usableWidth ) / 2 );
} else {
// reduce height:
usableWidth = w;
usableHeight = diagramNativeRectangle.height() * w;
zeroZeroPoint.setY( zeroZeroPoint.y() - ( h - usableHeight ) / 2 );
}
// the rectangle has 1 as it's width, and TriangleHeight as it's
// height - so this is how we translate that to widget coordinates:
d->xUnit = usableWidth / diagramNativeRectangle.width(); // only because we normalize the values to [0..1]
d->yUnit = -usableHeight / diagramNativeRectangle.height();
// now move zeroZeroPoint so that it does not include the tick marks
{
double descent = diagramNativeRectangle.height() - TriangleHeight;
double rightShift = -diagramNativeRectangle.x();
zeroZeroPoint += QPointF( rightShift * d->xUnit, descent * d->yUnit );
}
d->diagramRect.setBottomLeft( zeroZeroPoint );
d->diagramRect.setTopRight( QPointF( usableWidth, -usableHeight ) + zeroZeroPoint );
}
const QPointF TernaryCoordinatePlane::translate( const QPointF& point ) const
{
return QPointF( d->diagramRect.bottomLeft().x() + point.x() * d->xUnit,
d->diagramRect.bottomLeft().y() + point.y() * d->yUnit );
}
QSize TernaryCoordinatePlane::minimumSizeHint() const
{
// FIXME temp
return QSize();
}
QSizePolicy TernaryCoordinatePlane::sizePolicy() const
{
return QSizePolicy( QSizePolicy::MinimumExpanding,
QSizePolicy::MinimumExpanding );
}
void TernaryCoordinatePlane::paint( QPainter* painter )
{
PainterSaver s( painter );
// FIXME: this is not a good location for that:
painter->setRenderHint(QPainter::Antialiasing, true );
// painter->setPen( QColor( "gold" ) );
// painter->setBrush( QColor( "gold" ) );
// painter->drawRect( d->diagramRectContainer );
AbstractDiagramList diags = diagrams();
if ( !diags.isEmpty() )
{
PaintContext ctx;
ctx.setPainter ( painter );
ctx.setCoordinatePlane ( this );
const QRectF drawArea( areaGeometry() );
ctx.setRectangle ( drawArea );
// enabling clipping so that we're not drawing outside
// QRect clipRect = drawArea.toRect().adjusted( -1, -1, 1, 1 );
// QRegion clipRegion( clipRect );
// painter->setClipRegion( clipRegion );
// paint the coordinate system rulers:
Q_ASSERT( d->grid != 0 );
d->grid->drawGrid( &ctx );
// paint the diagrams:
for ( int i = 0; i < diags.size(); i++ )
{
PainterSaver diagramPainterSaver( painter );
diags[i]->paint ( &ctx );
}
}
}
DataDimensionsList TernaryCoordinatePlane::getDataDimensionsList() const
{ // not needed
return DataDimensionsList();
}
TernaryGrid* TernaryCoordinatePlane::grid() const
{
TernaryGrid* ternaryGrid = static_cast<TernaryGrid*>( d->grid );
Q_ASSERT( dynamic_cast<TernaryGrid*>( d->grid ) );
return ternaryGrid;
}
#undef d

View File

@@ -0,0 +1,66 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTTERNARYCOORDINATEPLANE_H
#define KDCHARTTERNARYCOORDINATEPLANE_H
#include "../KDChartAbstractCoordinatePlane.h"
namespace KDChart {
class TernaryGrid;
/**
* @brief Ternary coordinate plane
*/
class KDCHART_EXPORT TernaryCoordinatePlane
: public AbstractCoordinatePlane
{
Q_OBJECT
Q_DISABLE_COPY( TernaryCoordinatePlane )
KDCHART_DECLARE_PRIVATE_DERIVED_PARENT( TernaryCoordinatePlane, Chart* )
public:
explicit TernaryCoordinatePlane( Chart* parent = 0 );
~TernaryCoordinatePlane();
void addDiagram( AbstractDiagram* diagram );
void layoutDiagrams();
const QPointF translate ( const QPointF& diagramPoint ) const;
void paint( QPainter* );
DataDimensionsList getDataDimensionsList() const;
/** \reimpl */
QSize minimumSizeHint() const;
/** \reimpl */
QSizePolicy sizePolicy() const;
private:
TernaryGrid* grid() const;
};
}
#endif

View File

@@ -0,0 +1,90 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTTERNARYCOORDINATEPLANE_P_H
#define KDCHARTTERNARYCOORDINATEPLANE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the KD Chart API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QRectF>
#include "KDChartTernaryGrid.h"
#include "KDChartAbstractCoordinatePlane_p.h"
#include <KDABLibFakes>
namespace KDChart {
class TernaryAxis;
/**
* \internal
*/
class TernaryCoordinatePlane::Private : public AbstractCoordinatePlane::Private
{
friend class TernaryCoordinatePlane;
public:
explicit Private();
virtual ~Private() {
// grid is delete in base class dtor
}
virtual void initialize()
{
grid = new TernaryGrid();
xUnit = 0.0;
yUnit = 0.0;
}
QList<TernaryAxis*> axes;
TextAttributes labelAttributes;
// the diagram is drawn within this rectangle, which is within
// this widget:
QRectF diagramRectContainer;
// this is the "frame" of the plot area
QRectF diagramRect;
// multiply m_xUnit with a [0..1] value to get an isometric
// widget coordinate
double xUnit;
// same for y:
double yUnit;
};
KDCHART_IMPL_DERIVED_PLANE(TernaryCoordinatePlane, AbstractCoordinatePlane)
}
#endif /* KDCHARTTERNARYCOORDINATEPLANE_P_H */

View File

@@ -0,0 +1,216 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "KDChartTernaryGrid.h"
#include <cmath>
#include <algorithm>
#include <limits>
#include <QtDebug>
#include <QApplication>
#include "TernaryPoint.h"
#include "TernaryConstants.h"
#include "KDChartPaintContext.h"
#include "KDChartPainterSaver_p.h"
#include "KDChartTernaryCoordinatePlane.h"
#include "KDChartPrintingParameters.h"
using namespace KDChart;
TickInfo::TickInfo( double _percentage, int _depth )
: percentage ( _percentage )
, depth( _depth )
{
}
bool KDChart::operator==(const TickInfo& left, const TickInfo& right)
{
return fabs( left.percentage - right.percentage )
<= std::numeric_limits<double>::epsilon()
&& left.depth == right.depth;
}
TernaryGrid::TernaryGrid()
: AbstractGrid()
{
}
TernaryGrid::~TernaryGrid()
{
}
void TernaryGrid::drawGrid( PaintContext* context )
{
static const int GridLineDistanceTreshold = 20; // <Treshold> pixels between each grid line
QPainter& painter = *context->painter(); // recover from pointer madness
PainterSaver s( &painter ); // can i have a reference based version of that?
TernaryCoordinatePlane* plane = dynamic_cast<TernaryCoordinatePlane*>(context->coordinatePlane());
Q_ASSERT_X ( plane, "TernaryGrid::drawGrid",
"Bad function call: PaintContext::coodinatePlane() NOT a ternary plane." );
// translate the points and see how many grid lines we can draw:
const int MaxDepth = 3;
double xPixels = plane->translate( TriangleBottomRight ).x() -
plane->translate( TriangleBottomLeft ).x();
int granularity = 20;
if ( xPixels > 10 * GridLineDistanceTreshold ) granularity = 10;
if ( xPixels > 20 * GridLineDistanceTreshold ) granularity = 5;
m_tickInfo.clear();
for ( int i = granularity; i < 100; i+=granularity )
{
TickInfo tick( ( 1.0 * i ) / 100.0, 2 );
if ( i % 10 == 0 ) tick.depth = 1;
if ( i % 20 == 0 ) tick.depth = 0;
m_tickInfo.append( tick );
}
QVector<QLineF> lines[MaxDepth];
{Q_FOREACH( const TickInfo& tick, m_tickInfo ) {
const double& percent = tick.percentage;
{ // draw parallels to B
TernaryPoint ternaryStart( percent, 1.0 - percent );
TernaryPoint ternaryEnd( 0.0, 1.0 - percent );
QPointF start( translate( ternaryStart ) );
QPointF end( translate( ternaryEnd ) );
lines[tick.depth].append( QLineF( plane->translate( start ),
plane->translate( end ) ) );
}
{ // draw parallels to C
TernaryPoint ternaryStart( percent, 0.0 );
TernaryPoint ternaryEnd( 0.0, percent );
QPointF start( translate( ternaryStart ) );
QPointF end( translate( ternaryEnd ) );
lines[tick.depth].append( QLineF( plane->translate( start ),
plane->translate( end ) ) );
}
{ // draw parallels to A
TernaryPoint ternaryStart( percent, 1.0 - percent );
TernaryPoint ternaryEnd( percent, 0.0 );
QPointF start( translate( ternaryStart ) );
QPointF end( translate( ternaryEnd ) );
lines[tick.depth].append( QLineF( plane->translate( start ),
plane->translate( end ) ) );
}
}}
// now draw the lines:
painter.setPen( PrintingParameters::scalePen( QPen( QColor( "lightgray" ), 1 ) ) );
painter.setBrush( QColor( "lightgray" ) );
painter.drawLines( lines[2] );
painter.setPen( PrintingParameters::scalePen( QPen( QColor( "gray" ), 1 ) ) );
painter.setBrush( QColor( "gray" ) );
painter.drawLines( lines[1] );
painter.setPen( PrintingParameters::scalePen( QPen( QColor( "darkslategray" ), 1 ) ) );
painter.setBrush( QColor( "darkslategray" ) );
painter.drawLines( lines[0] );
// now draw the triangle (this could be part of the axis, in fact):
painter.setPen( PrintingParameters::scalePen( QPen( Qt::black, 1 ) ) );
// make sure this does not fill, otherwise it wipes the contents
// of the triangle (doh!):
painter.setBrush( Qt::NoBrush );
QPolygonF points;
points << plane->translate( TriangleBottomLeft )
<< plane->translate( TriangleBottomRight )
<< plane->translate( TriangleTop );
painter.drawPolygon( points );
// now draw the ticks:
painter.setPen( PrintingParameters::scalePen( QPen( Qt::black ) ) );
painter.setBrush( Qt::black );
QVector<QLineF> ticks;
// prepare list of percentages, then calculate lines:
QVector<TickInfo> percentages( m_tickInfo );
// I have commented those out, I think it looks ugly if they are
// enabled:
// percentages.prepend( 0.0 );
// percentages.append( 1.0 );
// FIXME this may need a predicate that takes eplison into account
// (but it does not hurt, since it will not make the painter
// paint two lines):
percentages.erase( std::unique( percentages.begin(), percentages.end() ),
percentages.end() );
{Q_FOREACH( const TickInfo& tick, percentages ) {
const double& percent = tick.percentage;
{ // BC axis markers:
const QPointF markerDistance( FullMarkerDistanceBC
/ ( tick.depth + 1 ) );
QPointF start( percent, 0.0 );
ticks.append( QLineF( plane->translate( start ),
plane->translate( start - markerDistance ) ) );
}
{ // AC axis markers:
const QPointF markerDistance( FullMarkerDistanceAC
/ ( tick.depth + 1 ) );
const QPointF start( TriangleBottomRight + percent * AxisVector_C_A );
const QPointF end( start + markerDistance );
ticks.append( QLineF( plane->translate( start ),
plane->translate( end ) ) );
}
{
// AB axis markers:
const QPointF markerDistance( FullMarkerDistanceBA
/ ( tick.depth +1 ) );
const QPointF start( percent * AxisVector_B_A );
const QPointF end( start + markerDistance );
ticks.append( QLineF( plane->translate( start ),
plane->translate( end ) ) );
}
}}
painter.drawLines( ticks );
}
DataDimensionsList TernaryGrid::calculateGrid( const DataDimensionsList& ) const
{
return DataDimensionsList();
}
QPair<QSizeF, QSizeF> TernaryGrid::requiredMargins() const
{
// double topMargin = ( FullMarkerDistanceBA * RelMarkerLength ).x();
double topMargin = 0.0; // no markers on tip of triangle
double leftMargin = fabs( FullMarkerDistanceBA.x() );
double bottomMargin = fabs( FullMarkerDistanceBC.y() );
// qDebug() << "TernaryGrid::requiredMargins: leftMargin:" << leftMargin
// << ", bottomMargin:" << bottomMargin
// << ", topMargin:" << topMargin
// << ", FullMarkerDistanceBC:" << FullMarkerDistanceBC
// << ", FullMarkerDistanceBA:" << FullMarkerDistanceBA
// << ", FullMarkerDistanceAC:" << FullMarkerDistanceAC
// << ", RelMarkerLength:" << RelMarkerLength;
return QPair<QSizeF, QSizeF>
( QSizeF( leftMargin, topMargin ),
QSizeF( leftMargin, bottomMargin ) );
}
const QVector<TickInfo>& TernaryGrid::tickInfo() const
{
return m_tickInfo;
}

View File

@@ -0,0 +1,76 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTTERNARYGRID_H
#define KDCHARTTERNARYGRID_H
#include <QList>
#include "KDChartAbstractGrid.h"
#include "PrerenderedElements/KDChartTextLabelCache.h"
namespace KDChart {
struct TickInfo {
TickInfo( double percentage = 0, int depth = 0 );
double percentage;
int depth;
};
bool operator==(const TickInfo&, const TickInfo& );
class PaintContext;
// VERIFY: Grids are not public API, are they?
class TernaryGrid : public AbstractGrid
{
public:
TernaryGrid();
virtual ~TernaryGrid();
void drawGrid( PaintContext* context );
DataDimensionsList calculateGrid( const DataDimensionsList& rawDataDimensions ) const;
/** Returns two QSizeF objects specifying the dimension of the
margins needed between each corner of the diagram and the
border of the drawing area. Margins are required because
the tick marks are placed outside of the trianges
containing rectangle.
The margins are returned in <em>diagram coordinates</em>,
since the grid does not know about widget coordinates.
*/
QPair<QSizeF, QSizeF> requiredMargins() const;
/** Return the locations of the grid lines, so that axes can
draw axis rulers at the correct positions.
This information is valid after the grid has been
painted (that is, the axes need to be painted after the
grid. */
const QVector<TickInfo>& tickInfo() const;
private:
QVector<TickInfo> m_tickInfo;
// QList<PrerenderedLabel> m_labels;
};
}
#endif

View File

@@ -0,0 +1,160 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "KDChartTernaryLineDiagram.h"
#include "KDChartTernaryLineDiagram_p.h"
#include <limits>
#include <QPainter>
#include <KDChartPaintContext>
#include "KDChartLineAttributes.h"
#include "KDChartDataValueAttributes.h"
#include "KDChartMarkerAttributes.h"
#include "TernaryPoint.h"
#include "TernaryConstants.h"
#include "KDChartPainterSaver_p.h"
using namespace KDChart;
#define d d_func()
TernaryLineDiagram::Private::Private()
: AbstractTernaryDiagram::Private()
{
}
TernaryLineDiagram::TernaryLineDiagram ( QWidget* parent,
TernaryCoordinatePlane* plane )
: AbstractTernaryDiagram( new Private(), parent, plane )
{
init();
setDatasetDimensionInternal( 3 ); // the third column is implicit
DataValueAttributes dataValueAttributes;
dataValueAttributes.setVisible( true );
MarkerAttributes markerAttributes;
markerAttributes.setMarkerStyle( MarkerAttributes::MarkerCircle );
markerAttributes.setVisible( true );
dataValueAttributes.setMarkerAttributes( markerAttributes );
attributesModel()->setDefaultForRole(
KDChart::DataValueLabelAttributesRole,
qVariantFromValue( dataValueAttributes ) );
}
TernaryLineDiagram::~TernaryLineDiagram()
{
}
void TernaryLineDiagram::init()
{
}
void TernaryLineDiagram::resize (const QSizeF& area)
{
Q_UNUSED( area );
}
void TernaryLineDiagram::paint (PaintContext *paintContext)
{
d->reverseMapper.clear();
d->paint( paintContext );
// sanity checks:
if ( model() == 0 ) return;
QPainter* p = paintContext->painter();
PainterSaver s( p );
TernaryCoordinatePlane* plane =
(TernaryCoordinatePlane*) paintContext->coordinatePlane();
Q_ASSERT( plane );
double x, y, z;
// for some reason(?) TernaryPointDiagram is using per-diagram DVAs only:
const DataValueAttributes attrs( dataValueAttributes() );
d->clearListOfAlreadyDrawnDataValueTexts();
int columnCount = model()->columnCount( rootIndex() );
QPointF start;
for(int column=0; column<columnCount; column+=datasetDimension() )
{
int numrows = model()->rowCount( rootIndex() );
for( int row = 0; row < numrows; row++ )
{
// see if there is data otherwise skip
QModelIndex base = model()->index( row, column );
if( ! model()->data( base ).isNull() )
{
p->setPen( PrintingParameters::scalePen( pen( base ) ) );
p->setBrush( brush( base ) );
// retrieve data
x = qMax( model()->data( model()->index( row, column, rootIndex() ) ).toDouble(),
0.0 );
y = qMax( model()->data( model()->index( row, column+1, rootIndex() ) ).toDouble(),
0.0 );
z = qMax( model()->data( model()->index( row, column+2, rootIndex() ) ).toDouble(),
0.0 );
double total = x + y + z;
if ( fabs( total ) > 3 * std::numeric_limits<double>::epsilon() ) {
TernaryPoint tPunkt( x / total, y / total );
QPointF diagramLocation = translate( tPunkt );
QPointF widgetLocation = plane->translate( diagramLocation );
if ( row > 0 ) {
p->drawLine( start, widgetLocation );
}
paintMarker( p, model()->index( row, column, rootIndex() ), widgetLocation );
start = widgetLocation;
// retrieve text and data value attributes
// FIXME use data model DisplayRole text
QString text = tr( "(%1, %2, %3)" )
.arg( x * 100, 0, 'f', 0 )
.arg( y * 100, 0, 'f', 0 )
.arg( z * 100, 0, 'f', 0 );
d->paintDataValueText( this, p, attrs, widgetLocation, text, true );
} else {
// ignore and do not paint this point, garbage data
qDebug() << "TernaryPointDiagram::paint: data point x/y/z:"
<< x << "/" << y << "/" << z << "ignored, unusable.";
}
}
}
}
}
const QPair< QPointF, QPointF > TernaryLineDiagram::calculateDataBoundaries () const
{
// this is a constant, because we defined it to be one:
static QPair<QPointF, QPointF> Boundaries(
TriangleBottomLeft,
QPointF( TriangleBottomRight.x(), TriangleHeight ) );
return Boundaries;
}

View File

@@ -0,0 +1,54 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTTERNARYLINEDIAGRAM_H
#define KDCHARTTERNARYLINEDIAGRAM_H
#include "KDChartTernaryCoordinatePlane.h"
#include "KDChartAbstractTernaryDiagram.h"
namespace KDChart {
/**
* @brief A TernaryLineDiagram is a line diagram with a ternary coordinate plane
*/
class KDCHART_EXPORT TernaryLineDiagram : public AbstractTernaryDiagram
{
Q_OBJECT
Q_DISABLE_COPY( TernaryLineDiagram )
KDCHART_DECLARE_DERIVED_DIAGRAM( TernaryLineDiagram, TernaryCoordinatePlane )
public:
explicit TernaryLineDiagram ( QWidget* parent = 0, TernaryCoordinatePlane* plane = 0 );
virtual ~TernaryLineDiagram();
void resize (const QSizeF &area);
void paint (PaintContext *paintContext);
protected:
const QPair< QPointF, QPointF > calculateDataBoundaries () const;
};
}
#endif

View File

@@ -0,0 +1,73 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTTERNARYLINEDIAGRAM_P_H
#define KDCHARTTERNARYLINEDIAGRAM_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the KD Chart API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "KDChartAbstractTernaryDiagram_p.h"
#include <KDABLibFakes>
namespace KDChart {
/**
* \internal
*/
class TernaryLineDiagram::Private : public AbstractTernaryDiagram::Private
{
friend class TernaryLineDiagram;
public:
Private();
~Private() {}
Private( const Private& rhs )
: AbstractTernaryDiagram::Private( rhs )
{
}
};
KDCHART_IMPL_DERIVED_DIAGRAM( TernaryLineDiagram, AbstractTernaryDiagram, TernaryCoordinatePlane )
/*
inline LineDiagram::LineDiagram( Private * p, TernaryCoordinatePlane* plane )
: AbstractTernaryDiagram( p, plane ) { init(); }
inline LineDiagram::Private * LineDiagram::d_func()
{ return static_cast<Private*>( AbstractTernaryDiagram::d_func() ); }
inline const LineDiagram::Private * LineDiagram::d_func() const
{ return static_cast<const Private*>( AbstractTernaryDiagram::d_func() ); }
*/
}
#endif /* KDCHARTTERNARYLINEDIAGRAM_P_H */

View File

@@ -0,0 +1,142 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "KDChartTernaryPointDiagram.h"
#include "KDChartTernaryPointDiagram_p.h"
#include <limits>
#include <QPainter>
#include <KDChartPaintContext>
#include "TernaryPoint.h"
#include "TernaryConstants.h"
using namespace KDChart;
#define d d_func()
TernaryPointDiagram::Private::Private()
: AbstractTernaryDiagram::Private()
{
}
TernaryPointDiagram::TernaryPointDiagram ( QWidget* parent,
TernaryCoordinatePlane* plane )
: AbstractTernaryDiagram( new Private(), parent, plane )
{
init();
setDatasetDimensionInternal( 3 ); // the third column is implicit
}
TernaryPointDiagram::~TernaryPointDiagram()
{
}
void TernaryPointDiagram::init()
{
d->reverseMapper.setDiagram( this );
}
void TernaryPointDiagram::resize (const QSizeF& area)
{
Q_UNUSED( area );
}
void TernaryPointDiagram::paint (PaintContext *paintContext)
{
d->reverseMapper.clear();
d->paint( paintContext );
// sanity checks:
if ( model() == 0 ) return;
QPainter* p = paintContext->painter();
PainterSaver s( p );
TernaryCoordinatePlane* plane =
(TernaryCoordinatePlane*) paintContext->coordinatePlane();
Q_ASSERT( plane );
double x, y, z;
// for some reason(?) TernaryPointDiagram is using per-diagram DVAs only:
const DataValueAttributes attrs( dataValueAttributes() );
d->clearListOfAlreadyDrawnDataValueTexts();
int columnCount = model()->columnCount( rootIndex() );
for(int column=0; column<columnCount; column+=datasetDimension() )
{
int numrows = model()->rowCount( rootIndex() );
for( int row = 0; row < numrows; row++ )
{
QModelIndex base = model()->index( row, column, rootIndex() );
// see if there is data otherwise skip
if( ! model()->data( model()->index( row, column+0, rootIndex() ) ).isNull() )
{
p->setPen( PrintingParameters::scalePen( pen( base ) ) );
p->setBrush( brush( base ) );
// retrieve data
x = qMax( model()->data( model()->index( row, column+0, rootIndex() ) ).toDouble(),
0.0 );
y = qMax( model()->data( model()->index( row, column+1, rootIndex() ) ).toDouble(),
0.0 );
z = qMax( model()->data( model()->index( row, column+2, rootIndex() ) ).toDouble(),
0.0 );
// fix messed up data values (paint as much as possible)
double total = x + y + z;
if ( fabs( total ) > 3 * std::numeric_limits<double>::epsilon() ) {
TernaryPoint tPunkt( x / total, y / total );
QPointF diagramLocation = translate( tPunkt );
QPointF widgetLocation = plane->translate( diagramLocation );
paintMarker( p, model()->index( row, column, rootIndex() ), widgetLocation );
QString text = tr( "(%1, %2, %3)" )
.arg( x * 100, 0, 'f', 0 )
.arg( y * 100, 0, 'f', 0 )
.arg( z * 100, 0, 'f', 0 );
d->paintDataValueText( this, p, attrs, widgetLocation, text, true );
} else {
// ignore and do not paint this point, garbage data
qDebug() << "TernaryPointDiagram::paint: data point x/y/z:"
<< x << "/" << y << "/" << z << "ignored, unusable.";
}
}
}
}
}
const QPair< QPointF, QPointF > TernaryPointDiagram::calculateDataBoundaries () const
{
// this is a constant, because we defined it to be one:
static QPair<QPointF, QPointF> Boundaries(
TriangleBottomLeft,
QPointF( TriangleBottomRight.x(), TriangleHeight ) );
return Boundaries;
}

View File

@@ -0,0 +1,53 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTTERNARYPOINTDIAGRAM_H
#define KDCHARTTERNARYPOINTDIAGRAM_H
#include "KDChartTernaryCoordinatePlane.h"
#include "KDChartAbstractTernaryDiagram.h"
namespace KDChart {
/**
* @brief A TernaryPointDiagram is a point diagram within a ternary coordinate plane
*/
class KDCHART_EXPORT TernaryPointDiagram : public AbstractTernaryDiagram
{
Q_OBJECT
Q_DISABLE_COPY( TernaryPointDiagram )
KDCHART_DECLARE_DERIVED_DIAGRAM( TernaryPointDiagram, TernaryCoordinatePlane )
public:
explicit TernaryPointDiagram ( QWidget* parent = 0, TernaryCoordinatePlane* plane = 0 );
virtual ~TernaryPointDiagram();
virtual void resize (const QSizeF &area);
virtual void paint (PaintContext *paintContext);
protected:
virtual const QPair< QPointF, QPointF > calculateDataBoundaries () const;
};
}
#endif

View File

@@ -0,0 +1,75 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef KDCHARTTERNARYPOINTDIAGRAM_P_H
#define KDCHARTTERNARYPOINTDIAGRAM_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the KD Chart API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtDebug>
#include "KDChartAbstractTernaryDiagram_p.h"
#include <KDABLibFakes>
namespace KDChart {
/**
* \internal
*/
class TernaryPointDiagram::Private : public AbstractTernaryDiagram::Private
{
friend class TernaryPointDiagram;
public:
Private();
~Private() {}
Private( const Private& rhs )
: AbstractTernaryDiagram::Private( rhs )
{
}
};
KDCHART_IMPL_DERIVED_DIAGRAM( TernaryPointDiagram, AbstractTernaryDiagram, TernaryCoordinatePlane )
/*
inline TernaryPointDiagram::TernaryPointDiagram( Private * p, TernaryCoordinatePlane* plane )
: AbstractTernaryDiagram( p, plane ) { init(); }
inline TernaryPointDiagram::Private * TernaryPointDiagram::d_func()
{ return static_cast<Private*>( AbstractTernaryDiagram::d_func() ); }
inline const TernaryPointDiagram::Private * TernaryPointDiagram::d_func() const
{ return static_cast<const Private*>( AbstractTernaryDiagram::d_func() ); }
*/
}
#endif /* KDCHARTTERNARYPOINTDIAGRAM_P_H */

View File

@@ -0,0 +1,46 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "TernaryConstants.h"
#include <cmath>
using namespace std;
extern const double Sqrt3 = sqrt( 3.0 );
extern const double TriangleWidth = 1.0;
extern const double TriangleHeight = 0.5 * Sqrt3;
extern const QPointF TriangleTop( 0.5, TriangleHeight );
extern const QPointF TriangleBottomLeft( 0.0, 0.0 );
extern const QPointF TriangleBottomRight( 1.0, 0.0 );
extern const QPointF AxisVector_C_A( TriangleTop - TriangleBottomRight );
extern const QPointF Norm_C_A( -AxisVector_C_A.y(), AxisVector_C_A.x() );
extern const QPointF AxisVector_B_A( TriangleTop );
extern const QPointF Norm_B_A( -AxisVector_B_A.y(), AxisVector_B_A.x() );
extern const QPointF AxisVector_B_C( TriangleBottomRight );
extern const QPointF Norm_B_C( -AxisVector_B_C.y(), AxisVector_B_C.x() );
extern const double RelMarkerLength = 0.03 * TriangleWidth;
extern const QPointF FullMarkerDistanceBC( RelMarkerLength * Norm_B_C );
extern const QPointF FullMarkerDistanceAC( -RelMarkerLength * Norm_C_A );
extern const QPointF FullMarkerDistanceBA( RelMarkerLength * Norm_B_A );

View File

@@ -0,0 +1,45 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef TERNARYCONSTANTS_H
#define TERNARYCONSTANTS_H
#include <QPointF>
extern const double Sqrt3;
extern const double TriangleWidth;
extern const double TriangleHeight;
extern const QPointF TriangleTop;
extern const QPointF TriangleBottomLeft;
extern const QPointF TriangleBottomRight;
extern const QPointF AxisVector_C_A;
extern const QPointF Norm_C_A;
extern const QPointF AxisVector_B_A;
extern const QPointF Norm_B_A;
extern const QPointF AxisVector_B_C;
extern const QPointF Norm_B_C;
extern const double RelMarkerLength;
extern const QPointF FullMarkerDistanceBC;
extern const QPointF FullMarkerDistanceAC;
extern const QPointF FullMarkerDistanceBA;
#endif

View File

@@ -0,0 +1,104 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "TernaryPoint.h"
#include "TernaryConstants.h"
#include <limits>
#include <QChar>
#include <QTextStream>
TernaryPoint::TernaryPoint()
: m_a( -1.0 )
, m_b( -1.0 )
{
Q_ASSERT( !isValid() );
}
TernaryPoint::TernaryPoint( double a, double b )
: m_a( -1.0 )
, m_b( -1.0 )
{
set( a, b );
}
void TernaryPoint::set( double a, double b )
{
if ( a >= 0.0 && a <= 1.0
&& b >= 0.0 && b <= 1.0
&& 1.0 - a - b >= -2.0 * std::numeric_limits<double>::epsilon() ) {
m_a = a;
m_b = b;
Q_ASSERT( isValid() ); // more a test for isValid
} else {
m_a = -1.0;
m_b = -1.0;
Q_ASSERT( ! isValid() );
}
}
bool TernaryPoint::isValid() const
{
return
m_a >= 0.0 && m_a <= 1.0
&& m_b >= 0.0 && m_b <= 1.0
&& 1.0 - m_a + m_b >= - std::numeric_limits<double>::epsilon();
}
QDebug operator<<( QDebug stream, const TernaryPoint& point )
{
QString string;
QTextStream text( &string );
text << "[TernaryPoint: ";
if ( point.isValid() ) {
text.setFieldWidth( 2 );
text.setPadChar( QLatin1Char( '0' ) );
text << ( int ) ( point.a() * 100.0 ) << "%|"
<< ( int ) ( point.b() * 100.0 ) << "%|"
<< ( int ) ( point.c() * 100.0 ) << "%]";
} else {
text << "a=" << point.a() << " - b=" << point.b() << " - INVALID]";
}
stream << string;
return stream;
}
QPointF translate( const TernaryPoint& point )
{
if ( point.isValid() ) {
// the position is calculated by
// - first moving along the B-C line to the function that b
// selects
// - then traversing the selected function until we meet with
// the function that A selects (which is a parallel of the B-C
// line)
QPointF bPosition( 1.0 - point.b(), 0.0 );
QPointF aPosition( point.a() * AxisVector_C_A );
QPointF result( bPosition + aPosition );
return result;
} else {
qWarning() << "TernaryPoint::translate(TernaryPoint): cannot translate invalid ternary points:"
<< point;
return QPointF();
}
}

View File

@@ -0,0 +1,56 @@
/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#ifndef TERNARYPOINT_H
#define TERNARYPOINT_H
#include <QtDebug>
#include <QPointF>
/**
* @brief TernaryPoint defines a point within a ternary coordinate plane
* \internal
*/
class TernaryPoint
{
public:
TernaryPoint();
TernaryPoint( double a, double b );
double a() const { return m_a; }
double b() const { return m_b; }
double c() const { return 1.0 - m_a - m_b; }
void set( double a, double b );
bool isValid() const;
private:
double m_a;
double m_b;
};
QDebug operator<<( QDebug stream, const TernaryPoint& point );
QPointF translate( const TernaryPoint& );
#endif