28 {
29 using Type = T;
30
33
34 constexpr TPoint() = default;
35
36 template <class U>
37 explicit constexpr TPoint(const TPoint<U>& other)
38 : TPoint(static_cast<Type>(other.
x), static_cast<Type>(other.
y)) {}
39
40 template <class U>
41 explicit constexpr TPoint(const TSize<U>& other)
42 : TPoint(static_cast<Type>(other.
width),
43 static_cast<Type>(other.
height)) {}
44
45 constexpr TPoint(Type
x, Type
y) :
x(
x),
y(
y) {}
46
47 static constexpr TPoint<Type> MakeXY(Type
x, Type
y) {
return {
x,
y}; }
48
49 template <class U>
50 static constexpr TPoint Round(const TPoint<U>& other) {
51 return TPoint{static_cast<Type>(std::round(other.x)),
52 static_cast<Type>(std::round(other.y))};
53 }
54
55 constexpr bool operator==(
const TPoint& p)
const {
56 return p.x ==
x && p.y ==
y;
57 }
58
59 constexpr bool operator!=(
const TPoint& p)
const {
60 return p.x !=
x || p.y !=
y;
61 }
62
63 template <class U>
64 inline TPoint operator+=(const TPoint<U>& p) {
65 x +=
static_cast<Type
>(p.x);
66 y +=
static_cast<Type
>(p.y);
67 return *this;
68 }
69
70 template <class U>
71 inline TPoint operator+=(const TSize<U>& s) {
72 x +=
static_cast<Type
>(s.width);
73 y +=
static_cast<Type
>(s.height);
74 return *this;
75 }
76
77 template <class U>
78 inline TPoint operator-=(const TPoint<U>& p) {
79 x -=
static_cast<Type
>(p.x);
80 y -=
static_cast<Type
>(p.y);
81 return *this;
82 }
83
84 template <class U>
85 inline TPoint operator-=(const TSize<U>& s) {
86 x -=
static_cast<Type
>(s.width);
87 y -=
static_cast<Type
>(s.height);
88 return *this;
89 }
90
91 template <class U>
92 inline TPoint operator*=(const TPoint<U>& p) {
93 x *=
static_cast<Type
>(p.x);
94 y *=
static_cast<Type
>(p.y);
95 return *this;
96 }
97
98 template <class U>
99 inline TPoint operator*=(const TSize<U>& s) {
100 x *=
static_cast<Type
>(s.width);
101 y *=
static_cast<Type
>(s.height);
102 return *this;
103 }
104
105 template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
106 inline TPoint operator*=(U scale) {
107 x *=
static_cast<Type
>(scale);
108 y *=
static_cast<Type
>(scale);
109 return *this;
110 }
111
112 template <class U>
113 inline TPoint operator/=(const TPoint<U>& p) {
114 x /=
static_cast<Type
>(p.x);
115 y /=
static_cast<Type
>(p.y);
116 return *this;
117 }
118
119 template <class U>
120 inline TPoint operator/=(const TSize<U>& s) {
121 x /=
static_cast<Type
>(s.width);
122 y /=
static_cast<Type
>(s.height);
123 return *this;
124 }
125
126 template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
127 inline TPoint operator/=(U scale) {
128 x /=
static_cast<Type
>(scale);
129 y /=
static_cast<Type
>(scale);
130 return *this;
131 }
132
133 constexpr TPoint
operator-()
const {
return {-
x, -
y}; }
134
135 constexpr TPoint
operator+(
const TPoint& p)
const {
136 return {
x + p.x,
y + p.y};
137 }
138
139 template <class U>
140 constexpr TPoint
operator+(
const TSize<U>& s)
const {
141 return {
x +
static_cast<Type
>(s.width),
y +
static_cast<Type
>(s.height)};
142 }
143
144 constexpr TPoint
operator-(
const TPoint& p)
const {
145 return {
x - p.x,
y - p.y};
146 }
147
148 template <class U>
149 constexpr TPoint
operator-(
const TSize<U>& s)
const {
150 return {
x -
static_cast<Type
>(s.width),
y -
static_cast<Type
>(s.height)};
151 }
152
153 template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
154 constexpr TPoint
operator*(U scale)
const {
155 return {
static_cast<Type
>(
x * scale),
static_cast<Type
>(
y * scale)};
156 }
157
158 constexpr TPoint
operator*(
const TPoint& p)
const {
159 return {
x * p.x,
y * p.y};
160 }
161
162 template <class U>
163 constexpr TPoint
operator*(
const TSize<U>& s)
const {
164 return {
x *
static_cast<Type
>(s.width),
y *
static_cast<Type
>(s.height)};
165 }
166
167 template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
169 return {
static_cast<Type
>(
x /
d),
static_cast<Type
>(
y /
d)};
170 }
171
172 constexpr TPoint
operator/(
const TPoint& p)
const {
173 return {
x / p.x,
y / p.y};
174 }
175
176 template <class U>
177 constexpr TPoint
operator/(
const TSize<U>& s)
const {
178 return {
x /
static_cast<Type
>(s.width),
y /
static_cast<Type
>(s.height)};
179 }
180
181 constexpr Type GetDistanceSquared(const TPoint& p) const {
184 return dx * dx + dy * dy;
185 }
186
187 constexpr TPoint Min(const TPoint& p) const {
188 return {std::min<Type>(
x, p.x), std::min<Type>(
y, p.y)};
189 }
190
191 constexpr TPoint Max(const TPoint& p) const {
192 return {std::max<Type>(
x, p.x), std::max<Type>(
y, p.y)};
193 }
194
195 constexpr TPoint Floor()
const {
return {std::floor(
x), std::floor(
y)}; }
196
197 constexpr TPoint Ceil()
const {
return {std::ceil(
x), std::ceil(
y)}; }
198
199 constexpr TPoint Round()
const {
return {std::round(
x), std::round(
y)}; }
200
201 constexpr Type GetDistance(const TPoint& p) const {
202 return sqrt(GetDistanceSquared(p));
203 }
204
205 constexpr Type GetLengthSquared() const {
206 return static_cast<double>(
x) *
x +
static_cast<double>(
y) *
y;
207 }
208
209 constexpr Type GetLength() const { return std::sqrt(GetLengthSquared()); }
210
211
212
213
214
215
216
217
218 Type GetDistanceToSegmentSquared(TPoint p0, TPoint p1) const {
219
220 TPoint u = p1 - p0;
221 TPoint v = *this - p0;
222
223
225 if (dot <= 0) {
226
227
228 return v.GetLengthSquared();
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 Scalar uLengthSquared = u.GetLengthSquared();
246 if (dot >= uLengthSquared) {
247
248
249 return GetDistanceSquared(p1);
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263
264 Scalar cross = u.Cross(v);
265
266
267
268
269
270
271 return (cross / uLengthSquared) * cross;
272 }
273
274
275
276
277
278
279
280
281 constexpr Type GetDistanceToSegment(TPoint p0, TPoint p1) const {
282 return std::sqrt(GetDistanceToSegmentSquared(p0, p1));
283 }
284
285 constexpr TPoint Normalize() const {
286 const auto length = GetLength();
288 return {1, 0};
289 }
291 }
292
293 constexpr TPoint Abs()
const {
return {std::fabs(
x), std::fabs(
y)}; }
294
295 constexpr Type Cross(
const TPoint& p)
const {
return (
x * p.y) - (
y * p.x); }
296
297
298
299
300
301
302 static constexpr Type Cross(const TPoint& p0,
303 const TPoint& p1,
304 const TPoint& p2) {
305 return (p1 - p0).Cross(p2 - p0);
306 }
307
308 constexpr Type Dot(
const TPoint& p)
const {
return (
x * p.x) + (
y * p.y); }
309
310 constexpr TPoint Reflect(const TPoint& axis) const {
311 return *this - axis * this->Dot(axis) * 2;
312 }
313
314 constexpr TPoint Rotate(const Radians& angle) const {
315 const auto cos_a = std::cosf(angle.radians);
316 const auto sin_a = std::sinf(angle.radians);
317 return {
x * cos_a -
y * sin_a,
x * sin_a +
y * cos_a};
318 }
319
320
321
322
323 constexpr TPoint PerpendicularRight()
const {
return {-
y,
x}; }
324
325
326
327
328 constexpr TPoint PerpendicularLeft()
const {
return {
y, -
x}; }
329
330 constexpr Radians AngleTo(const TPoint& p) const {
331 return Radians{std::atan2(this->Cross(p), this->Dot(p))};
332 }
333
334 constexpr TPoint Lerp(const TPoint& p, Scalar t) const {
335 return *this + (p - *this) * t;
336 }
337
338 constexpr bool IsZero()
const {
return x == 0 &&
y == 0; }
339
341 IsFinite()
const {
return std::isfinite(
x) && std::isfinite(
y); }
342};
343
344
345
346template <class F, class I, class = MixedOp<F, I>>
347constexpr TPoint<F>
operator+(
const TPoint<F>& p1,
const TPoint<I>& p2) {
348 return {p1.x + static_cast<F>(p2.x), p1.y + static_cast<F>(p2.y)};
349}
350
351template <class F, class I, class = MixedOp<F, I>>
352constexpr TPoint<F>
operator+(
const TPoint<I>& p1,
const TPoint<F>& p2) {
353 return p2 + p1;
354}
355
356template <class F, class I, class = MixedOp<F, I>>
357constexpr TPoint<F>
operator-(
const TPoint<F>& p1,
const TPoint<I>& p2) {
358 return {p1.x - static_cast<F>(p2.x), p1.y - static_cast<F>(p2.y)};
359}
360
361template <class F, class I, class = MixedOp<F, I>>
362constexpr TPoint<F>
operator-(
const TPoint<I>& p1,
const TPoint<F>& p2) {
363 return {static_cast<F>(p1.x) - p2.x, static_cast<F>(p1.y) - p2.y};
364}
365
366template <class F, class I, class = MixedOp<F, I>>
367constexpr TPoint<F>
operator*(
const TPoint<F>& p1,
const TPoint<I>& p2) {
368 return {p1.x * static_cast<F>(p2.x), p1.y * static_cast<F>(p2.y)};
369}
370
371template <class F, class I, class = MixedOp<F, I>>
372constexpr TPoint<F>
operator*(
const TPoint<I>& p1,
const TPoint<F>& p2) {
373 return p2 * p1;
374}
375
376template <class F, class I, class = MixedOp<F, I>>
377constexpr TPoint<F>
operator/(
const TPoint<F>& p1,
const TPoint<I>& p2) {
378 return {p1.x / static_cast<F>(p2.x), p1.y / static_cast<F>(p2.y)};
379}
380
381template <class F, class I, class = MixedOp<F, I>>
382constexpr TPoint<F>
operator/(
const TPoint<I>& p1,
const TPoint<F>& p2) {
383 return {static_cast<F>(p1.x) / p2.x, static_cast<F>(p1.y) / p2.y};
384}
385
386
387
388template <class T, class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
389constexpr TPoint<T>
operator*(U s,
const TPoint<T>& p) {
390 return p * s;
391}
392
393template <class T, class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
394constexpr TPoint<T>
operator/(U s,
const TPoint<T>& p) {
395 return {static_cast<T>(s) / p.x, static_cast<T>(s) / p.y};
396}
397
398
399
400template <class T, class U>
401constexpr TPoint<T>
operator+(
const TSize<U>& s,
const TPoint<T>& p) {
402 return p + s;
403}
404
405template <class T, class U>
406constexpr TPoint<T>
operator-(
const TSize<U>& s,
const TPoint<T>& p) {
407 return {static_cast<T>(s.width) - p.x, static_cast<T>(s.height) - p.y};
408}
409
410template <class T, class U>
411constexpr TPoint<T>
operator*(
const TSize<U>& s,
const TPoint<T>& p) {
412 return p * s;
413}
414
415template <class T, class U>
416constexpr TPoint<T>
operator/(
const TSize<U>& s,
const TPoint<T>& p) {
417 return {static_cast<T>(s.width) / p.x, static_cast<T>(s.height) / p.y};
418}
419
420template <class T>
421constexpr TPoint<T>
operator-(
const TPoint<T>& p, T v) {
422 return {p.x - v, p.y - v};
423}
424
425using Point = TPoint<Scalar>;
426using IPoint = TPoint<int64_t>;
430using Quad = std::array<Point, 4>;
431
432[[maybe_unused]]
434 {1.0f, 0.0f},
435 {0.0f, 1.0f},
436 {-1.0f, 0.0f},
437 {0.0f, -1.0f},
438};
439
440#undef ONLY_ON_FLOAT
441#undef ONLY_ON_FLOAT_M
442
443}
444
446
447template <class T>
448inline std::ostream&
operator<<(std::ostream& out,
450 out <<
"(" << p.
x <<
", " << p.
y <<
")";
451 return out;
452}
453
454}
455
456#endif
bool operator==(const FlutterPoint &a, const FlutterPoint &b)
#define ONLY_ON_FLOAT_M(Modifiers, Return)
bool operator!=(const T &value, const UniqueObject< T, Traits > &object)
constexpr Color operator-(T value, const Color &c)
constexpr Color operator/(T value, const Color &c)
constexpr Color operator+(T value, const Color &c)
TPoint< int32_t > IPoint32
static constexpr impeller::Vector2 kQuadrantAxes[4]
constexpr Color operator*(T value, const Color &c)
TPoint< uint32_t > UintPoint32
std::array< Point, 4 > Quad
std::ostream & operator<<(std::ostream &out, const impeller::Arc &a)