File indexing completed on 2024-12-15 04:02:37

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 "TernaryPoint.h"
0010 #include "TernaryConstants.h"
0011 
0012 #include <limits>
0013 
0014 #include <QChar>
0015 #include <QTextStream>
0016 
0017 TernaryPoint::TernaryPoint()
0018     : m_a( -1.0 )
0019     , m_b( -1.0 )
0020 {
0021     Q_ASSERT( !isValid() );
0022 }
0023 
0024 TernaryPoint::TernaryPoint( qreal a, qreal b )
0025     : m_a( -1.0 )
0026     , m_b( -1.0 )
0027 {
0028     set( a, b );
0029 }
0030 
0031 void TernaryPoint::set( qreal a, qreal b )
0032 {
0033     if ( a >= 0.0 && a <= 1.0
0034          && b >= 0.0 && b <= 1.0
0035          && 1.0 - a - b >= -2.0 * std::numeric_limits<qreal>::epsilon() ) {
0036         m_a = a;
0037         m_b = b;
0038         Q_ASSERT( isValid() ); // more a test for isValid
0039     } else {
0040         m_a = -1.0;
0041         m_b = -1.0;
0042         Q_ASSERT( ! isValid() );
0043     }
0044 }
0045 
0046 bool TernaryPoint::isValid() const
0047 {
0048     return
0049         m_a >= 0.0 && m_a <= 1.0
0050         && m_b >= 0.0 && m_b <= 1.0
0051         && 1.0 - m_a + m_b >= - std::numeric_limits<qreal>::epsilon();
0052 }
0053 
0054 QDebug operator<<( QDebug stream, const TernaryPoint& point )
0055 {
0056     QString string;
0057     QTextStream text( &string );
0058     text << "[TernaryPoint: ";
0059     if ( point.isValid() ) {
0060         text.setFieldWidth( 2 );
0061         text.setPadChar( QLatin1Char( '0' ) );
0062         text << ( int ) ( point.a() * 100.0 ) << "%|"
0063              << ( int ) ( point.b() * 100.0 ) << "%|"
0064              << ( int ) ( point.c() * 100.0 ) << "%]";
0065     } else {
0066         text << "a=" << point.a() << " - b=" << point.b() << " - INVALID]";
0067     }
0068     stream << string;
0069     return stream;
0070 }
0071 
0072 QPointF translate( const TernaryPoint& point )
0073 {
0074     if ( point.isValid() ) {
0075         // the position is calculated by
0076         // - first moving along the B-C line to the function that b
0077         //   selects
0078         // - then traversing the selected function until we meet with
0079         //   the function that A selects (which is a parallel of the B-C
0080         //   line)
0081         QPointF bPosition( 1.0 - point.b(), 0.0 );
0082         QPointF aPosition( point.a() * AxisVector_C_A );
0083         QPointF result( bPosition + aPosition );
0084         return result;
0085     } else {
0086         qWarning() << "TernaryPoint::translate(TernaryPoint): cannot translate invalid ternary points:"
0087                    << point;
0088         return QPointF();
0089     }
0090 }