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