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.

240 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #pragma once
  18. //==============================================================================
  19. /**
  20. A pair of (x, y) coordinates.
  21. The ValueType template should be a primitive type such as int, float, double,
  22. rather than a class.
  23. @see Line, Path, AffineTransform
  24. */
  25. template <typename ValueType>
  26. class Point
  27. {
  28. public:
  29. /** Creates a point at the origin */
  30. Point() noexcept : x(), y() {}
  31. /** Creates a copy of another point. */
  32. Point (const Point& other) noexcept : x (other.x), y (other.y) {}
  33. /** Creates a point from an (x, y) position. */
  34. Point (ValueType initialX, ValueType initialY) noexcept : x (initialX), y (initialY) {}
  35. //==============================================================================
  36. /** Copies this point from another one. */
  37. Point& operator= (const Point& other) noexcept { x = other.x; y = other.y; return *this; }
  38. inline bool operator== (Point other) const noexcept { return x == other.x && y == other.y; }
  39. inline bool operator!= (Point other) const noexcept { return x != other.x || y != other.y; }
  40. /** Returns true if the point is (0, 0). */
  41. bool isOrigin() const noexcept { return x == ValueType() && y == ValueType(); }
  42. /** Returns true if the coordinates are finite values. */
  43. inline bool isFinite() const noexcept { return juce_isfinite(x) && juce_isfinite(y); }
  44. /** Returns the point's x coordinate. */
  45. inline ValueType getX() const noexcept { return x; }
  46. /** Returns the point's y coordinate. */
  47. inline ValueType getY() const noexcept { return y; }
  48. /** Sets the point's x coordinate. */
  49. inline void setX (ValueType newX) noexcept { x = newX; }
  50. /** Sets the point's y coordinate. */
  51. inline void setY (ValueType newY) noexcept { y = newY; }
  52. /** Returns a point which has the same Y position as this one, but a new X. */
  53. Point withX (ValueType newX) const noexcept { return Point (newX, y); }
  54. /** Returns a point which has the same X position as this one, but a new Y. */
  55. Point withY (ValueType newY) const noexcept { return Point (x, newY); }
  56. /** Changes the point's x and y coordinates. */
  57. void setXY (ValueType newX, ValueType newY) noexcept { x = newX; y = newY; }
  58. /** Adds a pair of coordinates to this value. */
  59. void addXY (ValueType xToAdd, ValueType yToAdd) noexcept { x += xToAdd; y += yToAdd; }
  60. //==============================================================================
  61. /** Returns a point with a given offset from this one. */
  62. Point translated (ValueType deltaX, ValueType deltaY) const noexcept { return Point (x + deltaX, y + deltaY); }
  63. /** Adds two points together */
  64. Point operator+ (Point other) const noexcept { return Point (x + other.x, y + other.y); }
  65. /** Adds another point's coordinates to this one */
  66. Point& operator+= (Point other) noexcept { x += other.x; y += other.y; return *this; }
  67. /** Subtracts one points from another */
  68. Point operator- (Point other) const noexcept { return Point (x - other.x, y - other.y); }
  69. /** Subtracts another point's coordinates to this one */
  70. Point& operator-= (Point other) noexcept { x -= other.x; y -= other.y; return *this; }
  71. /** Multiplies two points together */
  72. template <typename OtherType>
  73. Point operator* (Point<OtherType> other) const noexcept { return Point ((ValueType) (x * other.x), (ValueType) (y * other.y)); }
  74. /** Multiplies another point's coordinates to this one */
  75. template <typename OtherType>
  76. Point& operator*= (Point<OtherType> other) noexcept { *this = *this * other; return *this; }
  77. /** Divides one point by another */
  78. template <typename OtherType>
  79. Point operator/ (Point<OtherType> other) const noexcept { return Point ((ValueType) (x / other.x), (ValueType) (y / other.y)); }
  80. /** Divides this point's coordinates by another */
  81. template <typename OtherType>
  82. Point& operator/= (Point<OtherType> other) noexcept { *this = *this / other; return *this; }
  83. /** Returns a point whose coordinates are multiplied by a given scalar value. */
  84. template <typename FloatType>
  85. Point operator* (FloatType multiplier) const noexcept { return Point ((ValueType) (x * multiplier), (ValueType) (y * multiplier)); }
  86. /** Returns a point whose coordinates are divided by a given scalar value. */
  87. template <typename FloatType>
  88. Point operator/ (FloatType divisor) const noexcept { return Point ((ValueType) (x / divisor), (ValueType) (y / divisor)); }
  89. /** Multiplies the point's coordinates by a scalar value. */
  90. template <typename FloatType>
  91. Point& operator*= (FloatType multiplier) noexcept { x = (ValueType) (x * multiplier); y = (ValueType) (y * multiplier); return *this; }
  92. /** Divides the point's coordinates by a scalar value. */
  93. template <typename FloatType>
  94. Point& operator/= (FloatType divisor) noexcept { x = (ValueType) (x / divisor); y = (ValueType) (y / divisor); return *this; }
  95. /** Returns the inverse of this point. */
  96. Point operator-() const noexcept { return Point (-x, -y); }
  97. //==============================================================================
  98. /** This type will be double if the Point's type is double, otherwise it will be float. */
  99. typedef typename TypeHelpers::SmallestFloatType<ValueType>::type FloatType;
  100. //==============================================================================
  101. /** Returns the straight-line distance between this point and the origin. */
  102. ValueType getDistanceFromOrigin() const noexcept { return juce_hypot (x, y); }
  103. /** Returns the straight-line distance between this point and another one. */
  104. ValueType getDistanceFrom (Point other) const noexcept { return juce_hypot (x - other.x, y - other.y); }
  105. /** Returns the square of the straight-line distance between this point and the origin. */
  106. ValueType getDistanceSquaredFromOrigin() const noexcept { return x * x + y * y; }
  107. /** Returns the square of the straight-line distance between this point and another one. */
  108. ValueType getDistanceSquaredFrom (Point other) const noexcept { return (*this - other).getDistanceSquaredFromOrigin(); }
  109. /** Returns the angle from this point to another one.
  110. Taking this point to be the centre of a circle, and the other point being a position on
  111. the circumference, the return value is the number of radians clockwise from the 12 o'clock
  112. direction.
  113. So 12 o'clock = 0, 3 o'clock = Pi/2, 6 o'clock = Pi, 9 o'clock = -Pi/2
  114. */
  115. FloatType getAngleToPoint (Point other) const noexcept
  116. {
  117. return static_cast<FloatType> (std::atan2 (static_cast<FloatType> (other.x - x),
  118. static_cast<FloatType> (y - other.y)));
  119. }
  120. /** Returns the point that would be reached by rotating this point clockwise
  121. about the origin by the specified angle.
  122. */
  123. Point rotatedAboutOrigin (ValueType angleRadians) const noexcept
  124. {
  125. return Point (x * std::cos (angleRadians) - y * std::sin (angleRadians),
  126. x * std::sin (angleRadians) + y * std::cos (angleRadians));
  127. }
  128. /** Taking this point to be the centre of a circle, this returns a point on its circumference.
  129. @param radius the radius of the circle.
  130. @param angle the angle of the point, in radians clockwise from the 12 o'clock position.
  131. */
  132. Point<FloatType> getPointOnCircumference (float radius, float angle) const noexcept
  133. {
  134. return Point<FloatType> (static_cast<FloatType> (x + radius * std::sin (angle)),
  135. static_cast<FloatType> (y - radius * std::cos (angle)));
  136. }
  137. /** Taking this point to be the centre of an ellipse, this returns a point on its circumference.
  138. @param radiusX the horizontal radius of the circle.
  139. @param radiusY the vertical radius of the circle.
  140. @param angle the angle of the point, in radians clockwise from the 12 o'clock position.
  141. */
  142. Point<FloatType> getPointOnCircumference (float radiusX, float radiusY, float angle) const noexcept
  143. {
  144. return Point<FloatType> (static_cast<FloatType> (x + radiusX * std::sin (angle)),
  145. static_cast<FloatType> (y - radiusY * std::cos (angle)));
  146. }
  147. /** Returns the dot-product of two points (x1 * x2 + y1 * y2). */
  148. FloatType getDotProduct (Point other) const noexcept { return x * other.x + y * other.y; }
  149. //==============================================================================
  150. /** Uses a transform to change the point's coordinates.
  151. This will only compile if ValueType = float!
  152. @see AffineTransform::transformPoint
  153. */
  154. void applyTransform (const AffineTransform& transform) noexcept { transform.transformPoint (x, y); }
  155. /** Returns the position of this point, if it is transformed by a given AffineTransform. */
  156. Point transformedBy (const AffineTransform& transform) const noexcept
  157. {
  158. return Point (static_cast<ValueType> (transform.mat00 * x + transform.mat01 * y + transform.mat02),
  159. static_cast<ValueType> (transform.mat10 * x + transform.mat11 * y + transform.mat12));
  160. }
  161. //==============================================================================
  162. /** Casts this point to a Point<int> object. */
  163. Point<int> toInt() const noexcept { return Point<int> (static_cast<int> (x), static_cast<int> (y)); }
  164. /** Casts this point to a Point<float> object. */
  165. Point<float> toFloat() const noexcept { return Point<float> (static_cast<float> (x), static_cast<float> (y)); }
  166. /** Casts this point to a Point<double> object. */
  167. Point<double> toDouble() const noexcept { return Point<double> (static_cast<double> (x), static_cast<double> (y)); }
  168. /** Casts this point to a Point<int> object using roundToInt() to convert the values. */
  169. Point<int> roundToInt() const noexcept { return Point<int> (juce::roundToInt (x), juce::roundToInt (y)); }
  170. /** Returns the point as a string in the form "x, y". */
  171. String toString() const { return String (x) + ", " + String (y); }
  172. //==============================================================================
  173. ValueType x; /**< The point's X coordinate. */
  174. ValueType y; /**< The point's Y coordinate. */
  175. };
  176. /** Multiplies the point's coordinates by a scalar value. */
  177. template <typename ValueType>
  178. Point<ValueType> operator* (ValueType value, Point<ValueType> p) noexcept { return p * value; }