The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

260 lines
13KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. //==============================================================================
  21. /**
  22. A pair of (x, y) coordinates.
  23. The ValueType template should be a primitive type such as int, float, double,
  24. rather than a class.
  25. @see Line, Path, AffineTransform
  26. @tags{Graphics}
  27. */
  28. template <typename ValueType>
  29. class Point
  30. {
  31. public:
  32. /** Creates a point at the origin */
  33. constexpr Point() = default;
  34. /** Creates a copy of another point. */
  35. constexpr Point (const Point&) = default;
  36. /** Creates a point from an (x, y) position. */
  37. constexpr Point (ValueType initialX, ValueType initialY) noexcept : x (initialX), y (initialY) {}
  38. //==============================================================================
  39. /** Copies this point from another one. */
  40. Point& operator= (const Point&) = default;
  41. constexpr inline bool operator== (Point other) const noexcept
  42. {
  43. const auto tie = [] (const Point& p) { return std::tie (p.x, p.y); };
  44. return tie (*this) == tie (other);
  45. }
  46. constexpr inline bool operator!= (Point other) const noexcept { return ! operator== (other); }
  47. /** Returns true if the point is (0, 0). */
  48. constexpr bool isOrigin() const noexcept { return operator== (Point()); }
  49. /** Returns true if the coordinates are finite values. */
  50. constexpr inline bool isFinite() const noexcept { return juce_isfinite (x) && juce_isfinite (y); }
  51. /** Returns the point's x coordinate. */
  52. constexpr inline ValueType getX() const noexcept { return x; }
  53. /** Returns the point's y coordinate. */
  54. constexpr inline ValueType getY() const noexcept { return y; }
  55. /** Sets the point's x coordinate. */
  56. inline void setX (ValueType newX) noexcept { x = newX; }
  57. /** Sets the point's y coordinate. */
  58. inline void setY (ValueType newY) noexcept { y = newY; }
  59. /** Returns a point which has the same Y position as this one, but a new X. */
  60. constexpr Point withX (ValueType newX) const noexcept { return Point (newX, y); }
  61. /** Returns a point which has the same X position as this one, but a new Y. */
  62. constexpr Point withY (ValueType newY) const noexcept { return Point (x, newY); }
  63. /** Changes the point's x and y coordinates. */
  64. void setXY (ValueType newX, ValueType newY) noexcept { x = newX; y = newY; }
  65. /** Adds a pair of coordinates to this value. */
  66. void addXY (ValueType xToAdd, ValueType yToAdd) noexcept { x += xToAdd; y += yToAdd; }
  67. //==============================================================================
  68. /** Returns a point with a given offset from this one. */
  69. constexpr Point translated (ValueType deltaX, ValueType deltaY) const noexcept { return Point (x + deltaX, y + deltaY); }
  70. /** Adds two points together */
  71. constexpr Point operator+ (Point other) const noexcept { return Point (x + other.x, y + other.y); }
  72. /** Adds another point's coordinates to this one */
  73. Point& operator+= (Point other) noexcept { x += other.x; y += other.y; return *this; }
  74. /** Subtracts one points from another */
  75. constexpr Point operator- (Point other) const noexcept { return Point (x - other.x, y - other.y); }
  76. /** Subtracts another point's coordinates to this one */
  77. Point& operator-= (Point other) noexcept { x -= other.x; y -= other.y; return *this; }
  78. /** Multiplies two points together */
  79. template <typename OtherType>
  80. constexpr Point operator* (Point<OtherType> other) const noexcept { return Point ((ValueType) (x * other.x), (ValueType) (y * other.y)); }
  81. /** Multiplies another point's coordinates to this one */
  82. template <typename OtherType>
  83. Point& operator*= (Point<OtherType> other) noexcept { *this = *this * other; return *this; }
  84. /** Divides one point by another */
  85. template <typename OtherType>
  86. constexpr Point operator/ (Point<OtherType> other) const noexcept { return Point ((ValueType) (x / other.x), (ValueType) (y / other.y)); }
  87. /** Divides this point's coordinates by another */
  88. template <typename OtherType>
  89. Point& operator/= (Point<OtherType> other) noexcept { *this = *this / other; return *this; }
  90. /** Returns a point whose coordinates are multiplied by a given scalar value. */
  91. template <typename OtherType>
  92. constexpr Point operator* (OtherType multiplier) const noexcept
  93. {
  94. using CommonType = std::common_type_t<ValueType, OtherType>;
  95. return Point ((ValueType) ((CommonType) x * (CommonType) multiplier),
  96. (ValueType) ((CommonType) y * (CommonType) multiplier));
  97. }
  98. /** Returns a point whose coordinates are divided by a given scalar value. */
  99. template <typename OtherType>
  100. constexpr Point operator/ (OtherType divisor) const noexcept
  101. {
  102. using CommonType = std::common_type_t<ValueType, OtherType>;
  103. return Point ((ValueType) ((CommonType) x / (CommonType) divisor),
  104. (ValueType) ((CommonType) y / (CommonType) divisor));
  105. }
  106. /** Multiplies the point's coordinates by a scalar value. */
  107. template <typename FloatType>
  108. Point& operator*= (FloatType multiplier) noexcept { x = (ValueType) (x * multiplier); y = (ValueType) (y * multiplier); return *this; }
  109. /** Divides the point's coordinates by a scalar value. */
  110. template <typename FloatType>
  111. Point& operator/= (FloatType divisor) noexcept { x = (ValueType) (x / divisor); y = (ValueType) (y / divisor); return *this; }
  112. /** Returns the inverse of this point. */
  113. constexpr Point operator-() const noexcept { return Point (-x, -y); }
  114. //==============================================================================
  115. /** This type will be double if the Point's type is double, otherwise it will be float. */
  116. using FloatType = TypeHelpers::SmallestFloatType<ValueType>;
  117. //==============================================================================
  118. /** Returns the straight-line distance between this point and the origin. */
  119. ValueType getDistanceFromOrigin() const noexcept { return juce_hypot (x, y); }
  120. /** Returns the straight-line distance between this point and another one. */
  121. ValueType getDistanceFrom (Point other) const noexcept { return juce_hypot (x - other.x, y - other.y); }
  122. /** Returns the square of the straight-line distance between this point and the origin. */
  123. constexpr ValueType getDistanceSquaredFromOrigin() const noexcept { return x * x + y * y; }
  124. /** Returns the square of the straight-line distance between this point and another one. */
  125. constexpr ValueType getDistanceSquaredFrom (Point other) const noexcept { return (*this - other).getDistanceSquaredFromOrigin(); }
  126. /** Returns the angle from this point to another one.
  127. Taking this point to be the centre of a circle, and the other point being a position on
  128. the circumference, the return value is the number of radians clockwise from the 12 o'clock
  129. direction.
  130. So 12 o'clock = 0, 3 o'clock = Pi/2, 6 o'clock = Pi, 9 o'clock = -Pi/2
  131. */
  132. FloatType getAngleToPoint (Point other) const noexcept
  133. {
  134. return static_cast<FloatType> (std::atan2 (static_cast<FloatType> (other.x - x),
  135. static_cast<FloatType> (y - other.y)));
  136. }
  137. /** Returns the point that would be reached by rotating this point clockwise
  138. about the origin by the specified angle.
  139. */
  140. Point rotatedAboutOrigin (ValueType angleRadians) const noexcept
  141. {
  142. return Point (x * std::cos (angleRadians) - y * std::sin (angleRadians),
  143. x * std::sin (angleRadians) + y * std::cos (angleRadians));
  144. }
  145. /** Taking this point to be the centre of a circle, this returns a point on its circumference.
  146. @param radius the radius of the circle.
  147. @param angle the angle of the point, in radians clockwise from the 12 o'clock position.
  148. */
  149. Point<FloatType> getPointOnCircumference (float radius, float angle) const noexcept
  150. {
  151. return Point<FloatType> (static_cast<FloatType> (x + radius * std::sin (angle)),
  152. static_cast<FloatType> (y - radius * std::cos (angle)));
  153. }
  154. /** Taking this point to be the centre of an ellipse, this returns a point on its circumference.
  155. @param radiusX the horizontal radius of the circle.
  156. @param radiusY the vertical radius of the circle.
  157. @param angle the angle of the point, in radians clockwise from the 12 o'clock position.
  158. */
  159. Point<FloatType> getPointOnCircumference (float radiusX, float radiusY, float angle) const noexcept
  160. {
  161. return Point<FloatType> (static_cast<FloatType> (x + radiusX * std::sin (angle)),
  162. static_cast<FloatType> (y - radiusY * std::cos (angle)));
  163. }
  164. /** Returns the dot-product of two points (x1 * x2 + y1 * y2). */
  165. constexpr FloatType getDotProduct (Point other) const noexcept { return x * other.x + y * other.y; }
  166. //==============================================================================
  167. /** Uses a transform to change the point's coordinates.
  168. This will only compile if ValueType = float!
  169. @see AffineTransform::transformPoint
  170. */
  171. void applyTransform (const AffineTransform& transform) noexcept { transform.transformPoint (x, y); }
  172. /** Returns the position of this point, if it is transformed by a given AffineTransform. */
  173. Point transformedBy (const AffineTransform& transform) const noexcept
  174. {
  175. return Point (static_cast<ValueType> (transform.mat00 * (float) x + transform.mat01 * (float) y + transform.mat02),
  176. static_cast<ValueType> (transform.mat10 * (float) x + transform.mat11 * (float) y + transform.mat12));
  177. }
  178. //==============================================================================
  179. /** Casts this point to a Point<int> object. */
  180. constexpr Point<int> toInt() const noexcept { return Point<int> (static_cast<int> (x), static_cast<int> (y)); }
  181. /** Casts this point to a Point<float> object. */
  182. constexpr Point<float> toFloat() const noexcept { return Point<float> (static_cast<float> (x), static_cast<float> (y)); }
  183. /** Casts this point to a Point<double> object. */
  184. constexpr Point<double> toDouble() const noexcept { return Point<double> (static_cast<double> (x), static_cast<double> (y)); }
  185. /** Casts this point to a Point<int> object using roundToInt() to convert the values. */
  186. constexpr Point<int> roundToInt() const noexcept { return Point<int> (juce::roundToInt (x), juce::roundToInt (y)); }
  187. /** Returns the point as a string in the form "x, y". */
  188. String toString() const { return String (x) + ", " + String (y); }
  189. //==============================================================================
  190. ValueType x{}; /**< The point's X coordinate. */
  191. ValueType y{}; /**< The point's Y coordinate. */
  192. };
  193. /** Multiplies the point's coordinates by a scalar value. */
  194. template <typename ValueType>
  195. Point<ValueType> operator* (ValueType value, Point<ValueType> p) noexcept { return p * value; }
  196. } // namespace juce