Flutter Impeller
point_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
8 #include "gtest/gtest.h"
9 
10 namespace impeller {
11 namespace testing {
12 
13 TEST(PointTest, Length) {
14  for (int i = 0; i < 21; i++) {
15  EXPECT_EQ(Point(i, 0).GetLengthSquared(), i * i) << "i: " << i;
16  EXPECT_EQ(Point(0, i).GetLengthSquared(), i * i) << "i: " << i;
17  EXPECT_EQ(Point(-i, 0).GetLengthSquared(), i * i) << "i: " << i;
18  EXPECT_EQ(Point(0, -i).GetLengthSquared(), i * i) << "i: " << i;
19 
20  EXPECT_EQ(Point(i, 0).GetLength(), i) << "i: " << i;
21  EXPECT_EQ(Point(0, i).GetLength(), i) << "i: " << i;
22  EXPECT_EQ(Point(-i, 0).GetLength(), i) << "i: " << i;
23  EXPECT_EQ(Point(0, -i).GetLength(), i) << "i: " << i;
24 
25  EXPECT_EQ(Point(i, i).GetLengthSquared(), 2 * i * i) << "i: " << i;
26  EXPECT_EQ(Point(-i, i).GetLengthSquared(), 2 * i * i) << "i: " << i;
27  EXPECT_EQ(Point(i, -i).GetLengthSquared(), 2 * i * i) << "i: " << i;
28  EXPECT_EQ(Point(-i, -i).GetLengthSquared(), 2 * i * i) << "i: " << i;
29 
30  EXPECT_FLOAT_EQ(Point(i, i).GetLength(), kSqrt2 * i) << "i: " << i;
31  EXPECT_FLOAT_EQ(Point(-i, i).GetLength(), kSqrt2 * i) << "i: " << i;
32  EXPECT_FLOAT_EQ(Point(i, -i).GetLength(), kSqrt2 * i) << "i: " << i;
33  EXPECT_FLOAT_EQ(Point(-i, -i).GetLength(), kSqrt2 * i) << "i: " << i;
34  }
35 }
36 
37 TEST(PointTest, Distance) {
38  for (int j = 0; j < 21; j++) {
39  for (int i = 0; i < 21; i++) {
40  {
41  Scalar d = i - j;
42 
43  EXPECT_EQ(Point(i, 0).GetDistanceSquared(Point(j, 0)), d * d)
44  << "i: " << i << ", j: " << j;
45  EXPECT_EQ(Point(0, i).GetDistanceSquared(Point(0, j)), d * d)
46  << "i: " << i << ", j: " << j;
47  EXPECT_EQ(Point(j, 0).GetDistanceSquared(Point(i, 0)), d * d)
48  << "i: " << i << ", j: " << j;
49  EXPECT_EQ(Point(0, j).GetDistanceSquared(Point(0, i)), d * d)
50  << "i: " << i << ", j: " << j;
51 
52  EXPECT_EQ(Point(i, 0).GetDistance(Point(j, 0)), std::abs(d))
53  << "i: " << i << ", j: " << j;
54  EXPECT_EQ(Point(0, i).GetDistance(Point(0, j)), std::abs(d))
55  << "i: " << i << ", j: " << j;
56  EXPECT_EQ(Point(j, 0).GetDistance(Point(i, 0)), std::abs(d))
57  << "i: " << i << ", j: " << j;
58  EXPECT_EQ(Point(0, j).GetDistance(Point(0, i)), std::abs(d))
59  << "i: " << i << ", j: " << j;
60  }
61 
62  {
63  Scalar d_squared = i * i + j * j;
64 
65  EXPECT_EQ(Point(i, 0).GetDistanceSquared(Point(0, j)), d_squared)
66  << "i: " << i << ", j: " << j;
67  EXPECT_EQ(Point(-i, 0).GetDistanceSquared(Point(0, j)), d_squared)
68  << "i: " << i << ", j: " << j;
69  EXPECT_EQ(Point(i, 0).GetDistanceSquared(Point(0, -j)), d_squared)
70  << "i: " << i << ", j: " << j;
71  EXPECT_EQ(Point(-i, 0).GetDistanceSquared(Point(0, -j)), d_squared)
72  << "i: " << i << ", j: " << j;
73 
74  Scalar d = std::sqrt(d_squared);
75 
76  EXPECT_FLOAT_EQ(Point(i, 0).GetDistance(Point(0, j)), d)
77  << "i: " << i << ", j: " << j;
78  EXPECT_FLOAT_EQ(Point(-i, 0).GetDistance(Point(0, j)), d)
79  << "i: " << i << ", j: " << j;
80  EXPECT_FLOAT_EQ(Point(i, 0).GetDistance(Point(0, -j)), d)
81  << "i: " << i << ", j: " << j;
82  EXPECT_FLOAT_EQ(Point(-i, 0).GetDistance(Point(0, -j)), d)
83  << "i: " << i << ", j: " << j;
84  }
85  }
86  }
87 }
88 
89 TEST(PointTest, PerpendicularLeft) {
90  EXPECT_EQ(Point(1, 0).PerpendicularLeft(), Point(0, -1));
91  EXPECT_EQ(Point(0, 1).PerpendicularLeft(), Point(1, 0));
92  EXPECT_EQ(Point(-1, 0).PerpendicularLeft(), Point(0, 1));
93  EXPECT_EQ(Point(0, -1).PerpendicularLeft(), Point(-1, 0));
94 
95  EXPECT_EQ(Point(1, 1).PerpendicularLeft(), Point(1, -1));
96  EXPECT_EQ(Point(-1, 1).PerpendicularLeft(), Point(1, 1));
97  EXPECT_EQ(Point(-1, -1).PerpendicularLeft(), Point(-1, 1));
98  EXPECT_EQ(Point(1, -1).PerpendicularLeft(), Point(-1, -1));
99 }
100 
101 TEST(PointTest, PerpendicularRight) {
102  EXPECT_EQ(Point(1, 0).PerpendicularRight(), Point(0, 1));
103  EXPECT_EQ(Point(0, 1).PerpendicularRight(), Point(-1, 0));
104  EXPECT_EQ(Point(-1, 0).PerpendicularRight(), Point(0, -1));
105  EXPECT_EQ(Point(0, -1).PerpendicularRight(), Point(1, 0));
106 
107  EXPECT_EQ(Point(1, 1).PerpendicularRight(), Point(-1, 1));
108  EXPECT_EQ(Point(-1, 1).PerpendicularRight(), Point(-1, -1));
109  EXPECT_EQ(Point(-1, -1).PerpendicularRight(), Point(1, -1));
110  EXPECT_EQ(Point(1, -1).PerpendicularRight(), Point(1, 1));
111 }
112 
113 namespace {
114 typedef std::pair<Scalar, Scalar> PtSegmentDistanceFunc(Point);
115 
116 void TestPointToSegmentGroup(Point segment0,
117  Point segment1,
118  Point p0,
119  Point delta,
120  int count,
121  PtSegmentDistanceFunc calc_distance) {
122  for (int i = 0; i < count; i++) {
123  auto [distance, squared] = calc_distance(p0);
124  EXPECT_FLOAT_EQ(p0.GetDistanceToSegmentSquared(segment0, segment1), squared)
125  << p0 << " => [" << segment0 << ", " << segment1 << "]";
126  EXPECT_FLOAT_EQ(p0.GetDistanceToSegmentSquared(segment1, segment0), squared)
127  << p0 << " => [" << segment0 << ", " << segment1 << "]";
128  EXPECT_FLOAT_EQ(p0.GetDistanceToSegment(segment0, segment1), distance)
129  << p0 << " => [" << segment0 << ", " << segment1 << "]";
130  EXPECT_FLOAT_EQ(p0.GetDistanceToSegment(segment1, segment0), distance)
131  << p0 << " => [" << segment0 << ", " << segment1 << "]";
132  p0 += delta;
133  }
134 }
135 } // namespace
136 
137 TEST(PointTest, PointToSegment) {
138  // Horizontal segment and points to the left of it on the same line.
139  TestPointToSegmentGroup(
140  // Segment
141  {10, 10}, {20, 10},
142  // Starting point, delta, count ({0,10} through {10,10})
143  {0, 10}, {1, 0}, 11,
144  // Distance computation
145  [](Point p) {
146  Scalar d = 10 - p.x;
147  return std::make_pair(d, d * d);
148  });
149 
150  // Horizontal segment and points on the segment.
151  TestPointToSegmentGroup(
152  // Segment
153  {10, 10}, {20, 10},
154  // Starting point, delta, count ({11,10} through {19, 10})
155  {11, 10}, {1, 0}, 9,
156  // Distance computation
157  [](Point p) { //
158  return std::make_pair(0.0f, 0.0f);
159  });
160 
161  // Horizontal segment and points to the right of it on the same line.
162  TestPointToSegmentGroup(
163  // Segment
164  {10, 10}, {20, 10},
165  // Starting point, delta, count ({20,10} through {30,10})
166  {20, 10}, {1, 0}, 11,
167  // Distance computation
168  [](Point p) {
169  Scalar d = p.x - 20;
170  return std::make_pair(d, d * d);
171  });
172 
173  // Vertical segment and points above the top of it on the same line.
174  TestPointToSegmentGroup(
175  // Segment
176  {10, 10}, {10, 20},
177  // Starting point, delta, count ({10,0} through {10,10})
178  {10, 0}, {0, 1}, 11,
179  // Distance computation
180  [](Point p) {
181  Scalar d = 10 - p.y;
182  return std::make_pair(d, d * d);
183  });
184 
185  // Vertical segment and points on the segment.
186  TestPointToSegmentGroup(
187  // Segment
188  {10, 10}, {10, 20},
189  // Starting point, delta, count ({10,11} through {10, 19})
190  {10, 11}, {0, 1}, 9,
191  // Distance computation
192  [](Point p) { //
193  return std::make_pair(0.0f, 0.0f);
194  });
195 
196  // Vertical segment and points below the bottom of it on the same line.
197  TestPointToSegmentGroup(
198  // Segment
199  {10, 10}, {10, 20},
200  // Starting point, delta, count ({10,20} through {10,30})
201  {10, 20}, {0, 1}, 11,
202  // Distance computation
203  [](Point p) {
204  Scalar d = p.y - 20;
205  return std::make_pair(d, d * d);
206  });
207 
208  // Horizontal segment and points 5 pixels above and to the left of it
209  // on the same line.
210  TestPointToSegmentGroup(
211  // Segment
212  {10, 10}, {20, 10},
213  // Starting point, delta, count ({0,5} through {10,5})
214  {0, 5}, {1, 0}, 11,
215  // Distance computation
216  [](Point p) {
217  Scalar d_sq = (10 - p.x) * (10 - p.x) + 25;
218  return std::make_pair(std::sqrt(d_sq), d_sq);
219  });
220 
221  // Horizontal segment and points 5 pixels directly above the segment.
222  TestPointToSegmentGroup(
223  // Segment
224  {10, 10}, {20, 10},
225  // Starting point, delta, count ({11,5} through {19, 5})
226  {11, 5}, {1, 0}, 9,
227  // Distance computation
228  [](Point p) { //
229  return std::make_pair(5.0f, 25.0f);
230  });
231 
232  // Horizontal segment and points 5 pixels above and to the right of it
233  // on the same line.
234  TestPointToSegmentGroup(
235  // Segment
236  {10, 10}, {20, 10},
237  // Starting point, delta, count ({20,5} through {30,5})
238  {20, 5}, {1, 0}, 11,
239  // Distance computation
240  [](Point p) {
241  Scalar d_sq = (p.x - 20) * (p.x - 20) + 25;
242  return std::make_pair(std::sqrt(d_sq), d_sq);
243  });
244 
245  // Vertical segment and points 5 pixels to the left and above the segment
246  // on the same line.
247  TestPointToSegmentGroup(
248  // Segment
249  {10, 10}, {10, 20},
250  // Starting point, delta, count ({5,0} through {5,10})
251  {5, 0}, {0, 1}, 11,
252  // Distance computation
253  [](Point p) {
254  Scalar d_sq = 25 + (10 - p.y) * (10 - p.y);
255  return std::make_pair(std::sqrt(d_sq), d_sq);
256  });
257 
258  // Vertical segment and points 5 pixels directly to the left of the segment.
259  TestPointToSegmentGroup(
260  // Segment
261  {10, 10}, {10, 20},
262  // Starting point, delta, count ({5,11} through {5,19,})
263  {5, 11}, {0, 1}, 9,
264  // Distance computation
265  [](Point p) { //
266  return std::make_pair(5.0f, 25.0f);
267  });
268 
269  // Vertical segment and points 5 pixels to the left and below the segment
270  // on the same line.
271  TestPointToSegmentGroup(
272  // Segment
273  {10, 10}, {10, 20},
274  // Starting point, delta, count ({20,5} through {30,5})
275  {5, 20}, {0, 1}, 11,
276  // Distance computation
277  [](Point p) {
278  Scalar d_sq = 25 + (p.y - 20) * (p.y - 20);
279  return std::make_pair(std::sqrt(d_sq), d_sq);
280  });
281 
282  // Diagonal segment and points up and to the right of the top of the segment.
283  TestPointToSegmentGroup(
284  // Segment
285  {10, 10}, {20, 20},
286  // Starting point, delta, count ({5,-5} through {15,5})
287  {5, -5}, {1, 1}, 11,
288  // Distance computation
289  [](Point p) {
290  Scalar d_sq = (p.x - 10) * (p.x - 10) + (p.y - 10) * (p.y - 10);
291  return std::make_pair(std::sqrt(d_sq), d_sq);
292  });
293 
294  // Diagonal segment and points up and to the right of the segment itself.
295  TestPointToSegmentGroup(
296  // Segment
297  {10, 10}, {20, 20},
298  // Starting point, delta, count ({15,5} through {24,14})
299  {15, 5}, {1, 1}, 9,
300  // Distance computation
301  [](Point p) {
302  Scalar d_sq = 50.0f;
303  return std::make_pair(std::sqrt(d_sq), d_sq);
304  });
305 
306  // Diagonal segment and points up and to the right of the bottom of the
307  // segment.
308  TestPointToSegmentGroup(
309  // Segment
310  {10, 10}, {20, 20},
311  // Starting point, delta, count ({25,15} through {35,25})
312  {25, 15}, {1, 1}, 11,
313  // Distance computation
314  [](Point p) {
315  Scalar d_sq = (p.x - 20) * (p.x - 20) + (p.y - 20) * (p.y - 20);
316  return std::make_pair(std::sqrt(d_sq), d_sq);
317  });
318 
319  // Diagonal segment and points down and to the left of the top of the segment.
320  TestPointToSegmentGroup(
321  // Segment
322  {10, 10}, {20, 20},
323  // Starting point, delta, count ({-5,5} through {5,15})
324  {-5, 5}, {1, 1}, 11,
325  // Distance computation
326  [](Point p) {
327  Scalar d_sq = (p.x - 10) * (p.x - 10) + (p.y - 10) * (p.y - 10);
328  return std::make_pair(std::sqrt(d_sq), d_sq);
329  });
330 
331  // Diagonal segment and points down and to the left of the segment itself.
332  TestPointToSegmentGroup(
333  // Segment
334  {10, 10}, {20, 20},
335  // Starting point, delta, count ({5,15} through {14,24})
336  {5, 15}, {1, 1}, 9,
337  // Distance computation
338  [](Point p) {
339  Scalar d_sq = 50.0f;
340  return std::make_pair(std::sqrt(d_sq), d_sq);
341  });
342 
343  // Diagonal segment and points down and to the left of the bottom of the
344  // segment.
345  TestPointToSegmentGroup(
346  // Segment
347  {10, 10}, {20, 20},
348  // Starting point, delta, count ({15,25} through {25,35})
349  {15, 25}, {1, 1}, 11,
350  // Distance computation
351  [](Point p) {
352  Scalar d_sq = (p.x - 20) * (p.x - 20) + (p.y - 20) * (p.y - 20);
353  return std::make_pair(std::sqrt(d_sq), d_sq);
354  });
355 }
356 
357 TEST(PointTest, CrossProductThreePoints) {
358  // Colinear
359  EXPECT_FLOAT_EQ(Point::Cross(Point(-1, 0), Point(0, 0), Point(1, 0)), 0);
360  EXPECT_FLOAT_EQ(Point::Cross(Point(1, 0), Point(0, 0), Point(-1, 0)), 0);
361 
362  // Right turn
363  EXPECT_FLOAT_EQ(Point::Cross(Point(-1, 0), Point(0, 0), Point(0, 1)), 1);
364  EXPECT_FLOAT_EQ(Point::Cross(Point(-2, 0), Point(0, 0), Point(0, 2)), 4);
365 
366  // Left turn
367  EXPECT_FLOAT_EQ(Point::Cross(Point(-1, 0), Point(0, 0), Point(0, -1)), -1);
368  EXPECT_FLOAT_EQ(Point::Cross(Point(-2, 0), Point(0, 0), Point(0, -2)), -4);
369 
370  // Convenient values for a less obvious left turn.
371  // p1 - p0 == (0, 0) - (3, -4) == (-3, 4)
372  // p2 - p0 == (1, 2) - (3, -4) == (-2, 6)
373  // product of the magnitude of the 2 legs and the sin of their angle
374  // (||(-3, 4)||) * (||(-2, 6)||) * sin(angle)
375  // 5 * sqrt(40) * sin(angle)
376  // angle = arcsin(4 / 5) - arcsin(6 / sqrt(40)) ~= -18.4349
377  // sin(angle) ~= -0.316227766
378  // 5 * sqrt(40) * sin(angle) == -10
379  // The math is cleaner with the cross product:
380  // (-3 * 6) - (-2 * 4) == -18 - -8 == -10
381  EXPECT_FLOAT_EQ(Point::Cross(Point(3, -4), Point(0, 0), Point(1, 2)), -10);
382 }
383 
384 } // namespace testing
385 } // namespace impeller
TEST(AllocationSizeTest, CanCreateTypedAllocations)
float Scalar
Definition: scalar.h:19
TPoint< Scalar > Point
Definition: point.h:425
constexpr float kSqrt2
Definition: constants.h:47
Type GetDistanceToSegmentSquared(TPoint p0, TPoint p1) const
Definition: point.h:218
constexpr Type GetDistanceToSegment(TPoint p0, TPoint p1) const
Definition: point.h:281
constexpr Type Cross(const TPoint &p) const
Definition: point.h:295