Skip to content

Commit 75e83ff

Browse files
bderodnfield
authored andcommitted
Point: Add reflect and make scalar ops more flexible (flutter#51)
1 parent d84a831 commit 75e83ff

File tree

2 files changed

+84
-7
lines changed

2 files changed

+84
-7
lines changed

impeller/geometry/geometry_unittests.cc

+58
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
#include "impeller/geometry/geometry_unittests.h"
6+
#include <limits>
67
#include "flutter/testing/testing.h"
78
#include "impeller/geometry/path.h"
89
#include "impeller/geometry/path_builder.h"
@@ -279,6 +280,38 @@ TEST(GeometryTest, CanPerformAlgebraicPointOps) {
279280
}
280281
}
281282

283+
TEST(GeometryTest, CanPerformAlgebraicPointOpsWithArithmeticTypes) {
284+
// LHS
285+
{
286+
IPoint p1(1, 2);
287+
IPoint p2 = p1 * 2.0f;
288+
ASSERT_EQ(p2.x, 2u);
289+
ASSERT_EQ(p2.y, 4u);
290+
}
291+
292+
{
293+
IPoint p1(2, 6);
294+
IPoint p2 = p1 / 2.0f;
295+
ASSERT_EQ(p2.x, 1u);
296+
ASSERT_EQ(p2.y, 3u);
297+
}
298+
299+
// RHS
300+
{
301+
IPoint p1(1, 2);
302+
IPoint p2 = 2.0f * p1;
303+
ASSERT_EQ(p2.x, 2u);
304+
ASSERT_EQ(p2.y, 4u);
305+
}
306+
307+
{
308+
IPoint p1(2, 6);
309+
IPoint p2 = 12.0f / p1;
310+
ASSERT_EQ(p2.x, 6u);
311+
ASSERT_EQ(p2.y, 2u);
312+
}
313+
}
314+
282315
TEST(GeometryTest, PointIntegerCoercesToFloat) {
283316
// Integer on LHS, float on RHS
284317
{
@@ -499,6 +532,31 @@ TEST(GeometryTest, PointCrossProduct) {
499532
}
500533
}
501534

535+
TEST(GeometryTest, PointReflect) {
536+
{
537+
Point axis = Point(0, 1);
538+
Point a(2, 3);
539+
auto reflected = a.Reflect(axis);
540+
auto expected = Point(2, -3);
541+
ASSERT_POINT_NEAR(reflected, expected);
542+
}
543+
544+
{
545+
Point axis = Point(1, 1).Normalize();
546+
Point a(1, 0);
547+
auto reflected = a.Reflect(axis);
548+
auto expected = Point(0, -1);
549+
ASSERT_POINT_NEAR(reflected, expected);
550+
}
551+
552+
{
553+
Point axis = Point(1, 1).Normalize();
554+
Point a(-1, -1);
555+
auto reflected = a.Reflect(axis);
556+
ASSERT_POINT_NEAR(reflected, -a);
557+
}
558+
}
559+
502560
TEST(GeometryTest, CanConvertBetweenDegressAndRadians) {
503561
{
504562
auto deg = Degrees{90.0};

impeller/geometry/point.h

+26-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <cmath>
99
#include <ostream>
1010
#include <string>
11+
#include <type_traits>
1112

1213
#include "impeller/geometry/scalar.h"
1314
#include "impeller/geometry/size.h"
@@ -121,8 +122,9 @@ struct TPoint {
121122
return {x - static_cast<Type>(s.width), y - static_cast<Type>(s.height)};
122123
}
123124

124-
constexpr TPoint operator*(Scalar scale) const {
125-
return {x * scale, y * scale};
125+
template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
126+
constexpr TPoint operator*(U scale) const {
127+
return {static_cast<Type>(x * scale), static_cast<Type>(y * scale)};
126128
}
127129

128130
constexpr TPoint operator*(const TPoint& p) const {
@@ -134,7 +136,10 @@ struct TPoint {
134136
return {x * static_cast<Type>(s.width), y * static_cast<Type>(s.height)};
135137
}
136138

137-
constexpr TPoint operator/(Scalar d) const { return {x / d, y / d}; }
139+
template <class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
140+
constexpr TPoint operator/(U d) const {
141+
return {static_cast<Type>(x / d), static_cast<Type>(y / d)};
142+
}
138143

139144
constexpr TPoint operator/(const TPoint& p) const {
140145
return {x / p.x, y / p.y};
@@ -175,11 +180,13 @@ struct TPoint {
175180
return {x / length, y / length};
176181
}
177182

178-
constexpr Scalar Cross(const TPoint& p) const {
179-
return (x * p.y) - (y * p.x);
180-
}
183+
constexpr Type Cross(const TPoint& p) const { return (x * p.y) - (y * p.x); }
181184

182-
constexpr Scalar Dot(const TPoint& p) const { return (x * p.x) + (y * p.y); }
185+
constexpr Type Dot(const TPoint& p) const { return (x * p.x) + (y * p.y); }
186+
187+
constexpr TPoint Reflect(const TPoint& axis) const {
188+
return *this - axis * this->Dot(axis) * 2;
189+
}
183190

184191
constexpr bool IsZero() const { return x == 0 && y == 0; }
185192
};
@@ -226,6 +233,18 @@ constexpr TPoint<F> operator/(const TPoint<I>& p1, const TPoint<F>& p2) {
226233
return {static_cast<F>(p1.x) / p2.x, static_cast<F>(p1.y) / p2.y};
227234
}
228235

236+
// RHS algebraic operations with arithmetic types.
237+
238+
template <class T, class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
239+
constexpr TPoint<T> operator*(U s, const TPoint<T>& p) {
240+
return p * s;
241+
}
242+
243+
template <class T, class U, class = std::enable_if_t<std::is_arithmetic_v<U>>>
244+
constexpr TPoint<T> operator/(U s, const TPoint<T>& p) {
245+
return {static_cast<T>(s) / p.x, static_cast<T>(s) / p.y};
246+
}
247+
229248
// RHS algebraic operations with TSize.
230249

231250
template <class T, class U>

0 commit comments

Comments
 (0)