Skip to content

Commit

Permalink
Rect union and intersection.
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmaygarde authored and dnfield committed Apr 27, 2022
1 parent 4234b34 commit 8e90d38
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 61 deletions.
18 changes: 18 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,24 @@ TEST_F(AiksTest, CanRenderClips) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_F(AiksTest, CanSaveLayerStandalone) {
Canvas canvas;

Paint red;
red.color = Color::Red();

Paint alpha;
alpha.color = Color::Red().WithAlpha(0.5);

canvas.SaveLayer(alpha);

canvas.DrawCircle({125, 125}, 125, red);

canvas.Restore();

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_F(AiksTest, CanRenderGroupOpacity) {
Canvas canvas;

Expand Down
103 changes: 69 additions & 34 deletions impeller/geometry/geometry_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -141,38 +141,6 @@ TEST(GeometryTest, QuaternionLerp) {
ASSERT_QUATERNION_NEAR(q3, expected);
}

TEST(GeometryTest, RectWithPoint) {
auto rect = Rect{};

auto expected = Rect{};

ASSERT_RECT_NEAR(rect, expected);

rect = rect.WithPoint({100, 100});
expected = Rect{0, 0, 100, 100};
ASSERT_RECT_NEAR(rect, expected);

rect = rect.WithPoint({-11, -12});
expected = Rect{-11, -12, 111, 112};
ASSERT_RECT_NEAR(rect, expected);

rect = rect.WithPoint({55, 65});
expected = Rect{-11, -12, 111, 112};
ASSERT_RECT_NEAR(rect, expected);

rect = rect.WithPoint({-25, 0});
expected = Rect{-25, -12, 125, 112};
ASSERT_RECT_NEAR(rect, expected);

rect = rect.WithPoint({0, -25});
expected = Rect{-25, -25, 125, 125};
ASSERT_RECT_NEAR(rect, expected);

rect = rect.WithPoint({125, 135});
expected = Rect{-25, -25, 150, 160};
ASSERT_RECT_NEAR(rect, expected);
}

TEST(GeometryTest, SimplePath) {
Path path;

Expand Down Expand Up @@ -216,7 +184,7 @@ TEST(GeometryTest, BoundingBoxCubic) {
Path path;
path.AddCubicComponent({120, 160}, {25, 200}, {220, 260}, {220, 40});
auto box = path.GetBoundingBox();
Rect expected(0, 0, 220, 198.862);
Rect expected(93.9101, 40, 126.09, 158.862);
ASSERT_RECT_NEAR(box, expected);
}

Expand All @@ -225,7 +193,7 @@ TEST(GeometryTest, BoundingBoxOfCompositePathIsCorrect) {
builder.AddRoundedRect({{10, 10}, {300, 300}}, {50, 50, 50, 50});
auto path = builder.CreatePath();
auto actual = path.GetBoundingBox();
Rect expected(0, 0, 310, 310);
Rect expected(10, 10, 300, 300);
ASSERT_RECT_NEAR(actual, expected);
}

Expand Down Expand Up @@ -273,5 +241,72 @@ TEST(GeometryTest, CanConvertBetweenDegressAndRadians) {
}
}

TEST(GeometryTest, RectUnion) {
{
Rect a(100, 100, 100, 100);
Rect b(0, 0, 0, 0);
auto u = a.Union(b);
auto expected = Rect(0, 0, 200, 200);
ASSERT_RECT_NEAR(u, expected);
}

{
Rect a(100, 100, 100, 100);
Rect b(10, 10, 0, 0);
auto u = a.Union(b);
auto expected = Rect(10, 10, 190, 190);
ASSERT_RECT_NEAR(u, expected);
}

{
Rect a(0, 0, 100, 100);
Rect b(10, 10, 100, 100);
auto u = a.Union(b);
auto expected = Rect(0, 0, 110, 110);
ASSERT_RECT_NEAR(u, expected);
}

{
Rect a(0, 0, 100, 100);
Rect b(100, 100, 100, 100);
auto u = a.Union(b);
auto expected = Rect(0, 0, 200, 200);
ASSERT_RECT_NEAR(u, expected);
}
}

TEST(GeometryTest, RectIntersection) {
{
Rect a(100, 100, 100, 100);
Rect b(0, 0, 0, 0);

auto u = a.Intersection(b);
ASSERT_FALSE(u.has_value());
}

{
Rect a(100, 100, 100, 100);
Rect b(10, 10, 0, 0);
auto u = a.Intersection(b);
ASSERT_FALSE(u.has_value());
}

{
Rect a(0, 0, 100, 100);
Rect b(10, 10, 100, 100);
auto u = a.Intersection(b);
ASSERT_TRUE(u.has_value());
auto expected = Rect(10, 10, 90, 90);
ASSERT_RECT_NEAR(u.value(), expected);
}

{
Rect a(0, 0, 100, 100);
Rect b(100, 100, 100, 100);
auto u = a.Intersection(b);
ASSERT_FALSE(u.has_value());
}
}

} // namespace testing
} // namespace impeller
55 changes: 31 additions & 24 deletions impeller/geometry/rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include <optional>
#include <ostream>
#include <vector>

Expand Down Expand Up @@ -87,35 +88,41 @@ struct TRect {

constexpr bool IsEmpty() const { return size.IsEmpty(); }

constexpr TRect WithPoint(const TPoint<Type>& p) const {
TRect copy = *this;
if (p.x < origin.x) {
copy.origin.x = p.x;
copy.size.width += (origin.x - p.x);
}

if (p.y < origin.y) {
copy.origin.y = p.y;
copy.size.height += (origin.y - p.y);
}
constexpr std::array<T, 4> GetLTRB() const {
const auto left = std::min(origin.x, origin.x + size.width);
const auto top = std::min(origin.y, origin.y + size.height);
const auto right = std::max(origin.x, origin.x + size.width);
const auto bottom = std::max(origin.y, origin.y + size.height);
return {left, top, right, bottom};
}

if (p.x > (size.width + origin.x)) {
copy.size.width += p.x - (size.width + origin.x);
}
constexpr TRect Union(const TRect& o) const {
auto this_ltrb = GetLTRB();
auto other_ltrb = o.GetLTRB();
return TRect::MakeLTRB(std::min(this_ltrb[0], other_ltrb[0]), //
std::min(this_ltrb[1], other_ltrb[1]), //
std::max(this_ltrb[2], other_ltrb[2]), //
std::max(this_ltrb[3], other_ltrb[3]) //
);
}

if (p.y > (size.height + origin.y)) {
copy.size.height += p.y - (size.height + origin.y);
constexpr std::optional<TRect<T>> Intersection(const TRect& o) const {
auto this_ltrb = GetLTRB();
auto other_ltrb = o.GetLTRB();
auto intersection =
TRect::MakeLTRB(std::max(this_ltrb[0], other_ltrb[0]), //
std::max(this_ltrb[1], other_ltrb[1]), //
std::min(this_ltrb[2], other_ltrb[2]), //
std::min(this_ltrb[3], other_ltrb[3]) //
);
if (intersection.size.IsEmpty()) {
return std::nullopt;
}

return copy;
return intersection;
}

constexpr TRect WithPoints(const std::vector<TPoint<Type>>& points) const {
TRect box = *this;
for (const auto& point : points) {
box = box.WithPoint(point);
}
return box;
constexpr bool IntersectsWithRect(const TRect& o) const {
return Interesection(o).has_value();
}
};

Expand Down
8 changes: 5 additions & 3 deletions impeller/geometry/size.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,13 @@ struct TSize {

constexpr Type Area() const { return width * height; }

constexpr bool IsZero() const { return width * height == 0.0; }
constexpr bool IsPositive() const { return width > 0 && height > 0; }

constexpr bool IsPositive() const { return width * height > 0.0; }
constexpr bool IsNegative() const { return width < 0 || height < 0; }

constexpr bool IsEmpty() const { return !IsPositive(); }
constexpr bool IsZero() const { return width == 0 || height == 0; }

constexpr bool IsEmpty() const { return IsNegative() || IsZero(); }

template <class U>
static constexpr TSize Ceil(const TSize<U>& other) {
Expand Down

0 comments on commit 8e90d38

Please sign in to comment.