File: quad_f.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (169 lines) | stat: -rw-r--r-- 6,298 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_GFX_GEOMETRY_QUAD_F_H_
#define UI_GFX_GEOMETRY_QUAD_F_H_

#include <stddef.h>

#include <algorithm>
#include <cmath>
#include <iosfwd>
#include <string>

#include "base/check_op.h"
#include "base/component_export.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect_f.h"

namespace gfx {

// A Quad is defined by four corners, allowing it to have edges that are not
// axis-aligned, unlike a Rect.
class COMPONENT_EXPORT(GEOMETRY) QuadF {
 public:
  constexpr QuadF() = default;
  constexpr QuadF(const PointF& p1,
                  const PointF& p2,
                  const PointF& p3,
                  const PointF& p4)
      : p1_(p1), p2_(p2), p3_(p3), p4_(p4) {}

  constexpr explicit QuadF(const RectF& rect)
      : p1_(rect.x(), rect.y()),
        p2_(rect.right(), rect.y()),
        p3_(rect.right(), rect.bottom()),
        p4_(rect.x(), rect.bottom()) {}

  void operator=(const RectF& rect);

  void set_p1(const PointF& p) { p1_ = p; }
  void set_p2(const PointF& p) { p2_ = p; }
  void set_p3(const PointF& p) { p3_ = p; }
  void set_p4(const PointF& p) { p4_ = p; }

  constexpr const PointF& p1() const { return p1_; }
  constexpr const PointF& p2() const { return p2_; }
  constexpr const PointF& p3() const { return p3_; }
  constexpr const PointF& p4() const { return p4_; }

  // Returns true if the quad is an axis-aligned rectangle.
  bool IsRectilinear() const;

  // Returns true if the points of the quad are in counter-clockwise order. This
  // assumes that the quad is convex, and that no three points are collinear.
  bool IsCounterClockwise() const;

  // Returns true if the |point| is contained within the quad, or lies on on
  // edge of the quad. This assumes that the quad is convex.
  bool Contains(const PointF& point) const;

  // Returns true if the |quad| parameter is contained within |this| quad.
  // This method assumes |this| quad is convex. The |quad| parameter has no
  // restrictions.
  bool ContainsQuad(const QuadF& quad) const;

  // Returns two points (forming an axis-aligned bounding box) that bounds the
  // four points of the quad.
  std::pair<PointF, PointF> Extents() const {
    float rl = std::min({p1_.x(), p2_.x(), p3_.x(), p4_.x()});
    float rr = std::max({p1_.x(), p2_.x(), p3_.x(), p4_.x()});
    float rt = std::min({p1_.y(), p2_.y(), p3_.y(), p4_.y()});
    float rb = std::max({p1_.y(), p2_.y(), p3_.y(), p4_.y()});
    return std::make_pair(PointF(rl, rt), PointF(rr, rb));
  }

  // Returns a rectangle that bounds the four points of the quad. The points of
  // the quad may lie on the right/bottom edge of the resulting rectangle,
  // rather than being strictly inside it.
  RectF BoundingBox() const {
    const auto [min, max] = Extents();
    return RectF(min.x(), min.y(), max.x() - min.x(), max.y() - min.y());
  }

  // Realigns the corners in the quad by rotating them n corners to the right.
  void Realign(size_t times) {
    DCHECK_LE(times, 4u);
    for (size_t i = 0; i < times; ++i) {
      PointF temp = p1_;
      p1_ = p2_;
      p2_ = p3_;
      p3_ = p4_;
      p4_ = temp;
    }
  }

  // Add a vector to the quad, offseting each point in the quad by the vector.
  void operator+=(const Vector2dF& rhs);
  // Subtract a vector from the quad, offseting each point in the quad by the
  // inverse of the vector.
  void operator-=(const Vector2dF& rhs);

  // Scale each point in the quad by the |scale| factor.
  void Scale(float scale) { Scale(scale, scale); }

  // Scale each point in the quad by the scale factors along each axis.
  void Scale(float x_scale, float y_scale);

  // Tests whether any part of the rectangle intersects with this quad.
  // This only works for convex quads.
  // This intersection is edge-inclusive and will return true even if the
  // intersecting area is empty (i.e., the intersection is a line or a point).
  bool IntersectsRect(const RectF&) const;

  // Like the above, but only checks `rect` against the sides of quad ("does
  // half of the job"). Can be used if it is known beforehand that the bounding
  // box of the quad intersects `rect`.
  bool IntersectsRectPartial(const RectF& rect) const;

  // Tests whether any part of the quad intersects with this quad.
  // This intersection is edge-inclusive.
  bool IntersectsQuad(const QuadF& quad) const;

  // Test whether any part of the circle/ellipse intersects with this quad.
  // Note that these two functions only work for convex quads.
  // These intersections are edge-inclusive and will return true even if the
  // intersecting area is empty (i.e., the intersection is a line or a point).
  bool IntersectsCircle(const PointF& center, float radius) const;
  bool IntersectsEllipse(const PointF& center, const SizeF& radii) const;

  // The center of the quad. If the quad is the result of a affine-transformed
  // rectangle this is the same as the original center transformed.
  PointF CenterPoint() const {
    return PointF((p1_.x() + p2_.x() + p3_.x() + p4_.x()) / 4.0,
                  (p1_.y() + p2_.y() + p3_.y() + p4_.y()) / 4.0);
  }

  // Returns a string representation of quad.
  std::string ToString() const;

  friend bool operator==(const QuadF&, const QuadF&) = default;

 private:
  bool IsToTheLeftOfOrTouchingLine(const PointF& base,
                                   const Vector2dF& vector) const;
  bool FullyOutsideOneEdge(const QuadF& quad) const;

  PointF p1_;
  PointF p2_;
  PointF p3_;
  PointF p4_;
};

// Add a vector to a quad, offseting each point in the quad by the vector.
COMPONENT_EXPORT(GEOMETRY)
QuadF operator+(const QuadF& lhs, const Vector2dF& rhs);
// Subtract a vector from a quad, offseting each point in the quad by the
// inverse of the vector.
COMPONENT_EXPORT(GEOMETRY)
QuadF operator-(const QuadF& lhs, const Vector2dF& rhs);

// This is declared here for use in gtest-based unit tests but is defined in
// the //ui/gfx:test_support target. Depend on that to use this in your unit
// test. This should not be used in production code - call ToString() instead.
void PrintTo(const QuadF& quad, ::std::ostream* os);

}  // namespace gfx

#endif  // UI_GFX_GEOMETRY_QUAD_F_H_