Perceptual Color

polarpointf.cpp
1// SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
2// SPDX-License-Identifier: BSD-2-Clause OR MIT
3
4// Own header
5#include "polarpointf.h"
6
7// Other includes
8#include "helpermath.h"
9#include "helperposixmath.h"
10#include <cmath>
11#include <qdebug.h>
12#include <qmath.h>
13#include <type_traits>
14
15namespace PerceptualColor
16{
17/** @brief Constructor
18 *
19 * Normalizes the given polar coordinates and constructs an object with
20 * the <em>normalized</em> polar coordinates. See the general class
21 * description for details about the normalization.
22 *
23 * @param newRadius the @ref radius() value
24 * @param newAngleDegree the @ref angleDegree() value */
25PolarPointF::PolarPointF(const double newRadius, const double newAngleDegree)
26 : m_angleDegree(newAngleDegree)
27 , m_radius(newRadius)
28{
29 normalizePolar360(m_radius, m_angleDegree);
30}
31
32/** @brief Constructor
33 *
34 * Constructs an object converting from the given Cartesian coordinates.
35 *
36 * If the Cartesian coordinates are (0, 0) than the @ref angleDegree (which is
37 * meaningless for a @ref radius of 0) is set to 0°.
38 *
39 * @param cartesianCoordiantes the Cartesian coordinates */
40PolarPointF::PolarPointF(const QPointF cartesianCoordiantes)
41{
42 m_radius = sqrt( //
43 pow(cartesianCoordiantes.x(), 2) + pow(cartesianCoordiantes.y(), 2));
44 if (m_radius == 0) {
45 m_angleDegree = 0;
46 return;
47 }
48 // NOTE As explained in https://en.wikipedia.org/wiki/Atan2
49 // the function std::atan2() can be used to calculate the angle without
50 // an “if” statement. However, it returns angles in the interval [-π, +π]
51 // while we need [0°, 360°], so finally we could avoind an “if” statement
52 // but need to add code for the range correction. Therefore, the current
53 // approach seems fine.
54 if (cartesianCoordiantes.y() >= 0) {
55 m_angleDegree = qRadiansToDegrees( //
56 acos(cartesianCoordiantes.x() / m_radius));
57 } else {
58 m_angleDegree = qRadiansToDegrees( //
59 2 * pi - acos(cartesianCoordiantes.x() / m_radius));
60 }
61}
62
63/** @brief Compares with another @ref PolarPointF
64 *
65 * @param other the polar coordinates to compare with
66 *
67 * @returns <tt>true</tt> if both, <tt>this</tt> and <tt>other</tt>,
68 * are the same point in the coordinate space. <tt>false</tt> otherwise.
69 * Therefore <tt>[@ref radius() 0, @ref angleDegree() 50]</tt> is considered
70 * to be the same point as <tt>[@ref radius() 0, @ref angleDegree() 80]</tt>
71 because the @ref angleDegree() is meaningless if the @ref radius() is 0.*/
72bool PolarPointF::isSamePoint(const PolarPointF other) const
73{
74 return (
75 // radius has to be identical
76 (m_radius == other.m_radius) &&
77 // angle has to be identical (except when radius is 0, because
78 // then angle is meaningless)
79 ((m_angleDegree == other.m_angleDegree) || (m_radius == 0)));
80}
81
82/** @brief Normalized radius
83 *
84 * @returns the normalized radius value, guaranteed to be ≥ 0. */
85double PolarPointF::radius() const
86{
87 return m_radius;
88}
89
90/** @brief Normalized angle
91 *
92 * @returns the normalized angle value (coordinates in degree), guaranteed to
93 * be 0° ≤ value < 360° */
94double PolarPointF::angleDegree() const
95{
96 return m_angleDegree;
97}
98
99/** @brief Convert to Cartesian coordinates
100 *
101 * @returns the corresponding Cartesian coordinates */
102QPointF PolarPointF::toCartesian() const
103{
104 return QPointF(m_radius * cos(qDegreesToRadians(m_angleDegree)), //
105 m_radius * sin(qDegreesToRadians(m_angleDegree)));
106}
107
108/** @internal
109 *
110 * @brief Adds QDebug() support for data type
111 * @ref PerceptualColor::PolarPointF
112 *
113 * @param dbg Existing debug object
114 * @param value Value to stream into the debug object
115 * @returns Debug object with value streamed in */
116QDebug operator<<(QDebug dbg, const PerceptualColor::PolarPointF value)
117{
118 dbg.nospace() //
119 << "PolarPointF(radius: " //
120 << value.radius() //
121 << ", angleDegree: " //
122 << value.angleDegree() //
123 << "°)";
124 return dbg.maybeSpace();
125}
126
127static_assert(std::is_trivially_copyable_v<PolarPointF>);
128// static_assert(std::is_trivial_v<PolarPointF>);
129
130static_assert(std::is_standard_layout_v<PolarPointF>);
131
132static_assert(std::is_default_constructible_v<PolarPointF>);
133// static_assert(std::is_trivially_default_constructible_v<PolarPointF>);
134static_assert(std::is_nothrow_default_constructible_v<PolarPointF>);
135
136static_assert(std::is_copy_constructible_v<PolarPointF>);
137static_assert(std::is_trivially_copy_constructible_v<PolarPointF>);
138static_assert(std::is_nothrow_copy_constructible_v<PolarPointF>);
139
140static_assert(std::is_move_constructible_v<PolarPointF>);
141static_assert(std::is_trivially_move_constructible_v<PolarPointF>);
142static_assert(std::is_nothrow_move_constructible_v<PolarPointF>);
143
144} // namespace PerceptualColor
QDebug operator<<(QDebug dbg, const DcrawInfoContainer &c)
The namespace of this library.
QDebug & maybeSpace()
QDebug & nospace()
qreal x() const const
qreal y() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:36 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.