Skip to content

Commit

Permalink
[共通] Rect::chamfered() #1268
Browse files Browse the repository at this point in the history
  • Loading branch information
Reputeless committed Oct 2, 2024
1 parent 360cd39 commit dc772d4
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 5 deletions.
17 changes: 16 additions & 1 deletion Siv3D/include/Siv3D/Rect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,22 @@ namespace s3d
constexpr RoundRect rounded(double r) const noexcept;

[[nodiscard]]
Polygon rounded(double tl, double tr, double br, double bl) const noexcept;
Polygon rounded(double tl, double tr, double br, double bl) const;

/// @brief 長方形を面取りした Polygon を返します。
/// @param size 面取りの大きさ
/// @return 面取りした Polygon
[[nodiscard]]
Polygon chamfered(double size) const;

/// @brief 長方形を面取りした Polygon を返します。
/// @param tl 左上の面取りの大きさ
/// @param tr 右上の面取りの大きさ
/// @param br 右下の面取りの大きさ
/// @param bl 左下の面取りの大きさ
/// @return 面取りした Polygon
[[nodiscard]]
Polygon chamfered(double tl, double tr, double br, double bl) const;

/// @brief 長方形を Quad として返します。
/// @return 長方形の Quad
Expand Down
19 changes: 17 additions & 2 deletions Siv3D/include/Siv3D/RectF.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -783,8 +783,23 @@ namespace s3d
constexpr RoundRect rounded(double r) const noexcept;

[[nodiscard]]
Polygon rounded(double tl, double tr, double br, double bl) const noexcept;

Polygon rounded(double tl, double tr, double br, double bl) const;

/// @brief 長方形を面取りした Polygon を返します。
/// @param size 面取りの大きさ
/// @return 面取りした Polygon
[[nodiscard]]
Polygon chamfered(double size) const;

/// @brief 長方形を面取りした Polygon を返します。
/// @param tl 左上の面取りの大きさ
/// @param tr 右上の面取りの大きさ
/// @param br 右下の面取りの大きさ
/// @param bl 左下の面取りの大きさ
/// @return 面取りした Polygon
[[nodiscard]]
Polygon chamfered(double tl, double tr, double br, double bl) const;

/// @brief 長方形を Rect として返します。
/// @return 長方形の Rect
[[nodiscard]]
Expand Down
12 changes: 11 additions & 1 deletion Siv3D/src/Siv3D/Rect/SivRect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ namespace s3d
return quad;
}

Polygon Rect::rounded(double tl, double tr, double br, double bl) const noexcept
Polygon Rect::rounded(double tl, double tr, double br, double bl) const
{
constexpr double epsilon = 0.001;

Expand Down Expand Up @@ -224,6 +224,16 @@ namespace s3d
return Polygon{ vertices };
}

Polygon Rect::chamfered(const double size) const
{
return RectF{ *this }.chamfered(size);
}

Polygon Rect::chamfered(const double tl, const double tr, const double br, const double bl) const
{
return RectF{ *this }.chamfered(tl, tr, br, bl);
}

LineString Rect::outline(const CloseRing closeRing) const
{
if (closeRing)
Expand Down
190 changes: 189 additions & 1 deletion Siv3D/src/Siv3D/RectF/SivRectF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ namespace s3d
return quad;
}

Polygon RectF::rounded(double tl, double tr, double br, double bl) const noexcept
Polygon RectF::rounded(double tl, double tr, double br, double bl) const
{
constexpr double epsilon = 0.001;

Expand Down Expand Up @@ -224,6 +224,194 @@ namespace s3d
return Polygon{ vertices };
}

Polygon RectF::chamfered(double s) const
{
if (s <= 0.0)
{
return asPolygon();
}

s = Min(s, (Min(w, h) * 0.5));

Array<Vec2> points;

// 上辺
if ((s * 2.0) < w)
{
points.emplace_back((x + s), y);
points.emplace_back((x + w - s), y);
}
else
{
points.emplace_back((x + w * 0.5), y);
}

// 右辺
if ((s * 2.0) < h)
{
points.emplace_back((x + w), (y + s));
points.emplace_back((x + w), (y + h - s));
}
else
{
points.emplace_back((x + w), (y + h * 0.5));
}

// 下辺
if ((s * 2.0) < w)
{
points.emplace_back((x + w - s), (y + h));
points.emplace_back((x + s), (y + h));
}
else
{
points.emplace_back((x + w * 0.5), (y + h));
}

// 左辺
if ((s * 2.0) < h)
{
points.emplace_back(x, (y + h - s));
points.emplace_back(x, (y + s));
}
else
{
points.emplace_back(x, (y + h * 0.5));
}

Array<TriangleIndex> indices(points.size() - 2);

for (Vertex2D::IndexType i = 0; i < indices.size(); ++i)
{
indices[i] = { 0, static_cast<Vertex2D::IndexType>(i + 1), static_cast<Vertex2D::IndexType>(i + 2) };
}

return Polygon{ points, indices, *this };
}

Polygon RectF::chamfered(double tl, double tr, double br, double bl) const
{
tl = Max(tl, 0.0);
tr = Max(tr, 0.0);
br = Max(br, 0.0);
bl = Max(bl, 0.0);

if (double top = (tl + tr);
w < top)
{
tl *= (w / top);
tr *= (w / top);
}

if (double right = (tr + br);
h < right)
{
tr *= (h / right);
br *= (h / right);
}

if (double bottom = (br + bl);
w < bottom)
{
br *= (w / bottom);
bl *= (w / bottom);
}

if (double left = (bl + tl);
h < left)
{
bl *= (h / left);
tl *= (h / left);
}

Array<Vec2> points;

// 左上
if (tl)
{
const Vec2 p0{ x, (y + tl) };
const Vec2 p1{ (x + tl), y };
points << p0;
points << p1;
}
else
{
points << this->tl();
}

// 右上
if (tr)
{
const Vec2 p0{ (x + w - tr), y };
const Vec2 p1{ (x + w), (y + tr) };

if (points.back() != p0)
{
points << p0;
}

points << p1;
}
else
{
points << this->tr();
}

// 右下
if (br)
{
const Vec2 p0{ (x + w), (y + h - br) };
const Vec2 p1{ (x + w - br), (y + h) };

if (points.back() != p0)
{
points << p0;
}

points << p1;
}
else
{
points << this->br();
}

// 左下
if (bl)
{
const Vec2 p0{ (x + bl), (y + h) };
const Vec2 p1{ x, (y + h - bl) };

if (points.back() != p0)
{
points << p0;
}

if (points.front() != p1)
{
points << p1;
}
}
else
{
const Vec2 p0 = this->bl();

if ((points.back() != p0)
&& (points.front() != p0))
{
points << p0;
}
}

Array<TriangleIndex> indices(points.size() - 2);

for (Vertex2D::IndexType i = 0; i < indices.size(); ++i)
{
indices[i] = { 0, static_cast<Vertex2D::IndexType>(i + 1), static_cast<Vertex2D::IndexType>(i + 2) };
}

return Polygon{ points, indices, *this };
}

LineString RectF::outline(const CloseRing closeRing) const
{
if (closeRing)
Expand Down

0 comments on commit dc772d4

Please sign in to comment.