圆角矩形由矩形加四个等半径四分之一圆弧构成,点在内部的判定需分区域:先粗筛是否在包围矩形内,再判断是否在内矩形或某角的圆弧影响区内,通过距离平方比较避免浮点误差;不等圆角时需归一化为单位圆判断。

圆角矩形的数学定义与关键参数
圆角矩形不是标准几何图元,它由一个中心对齐(或左上对齐)的矩形 + 四个相同半径的四分之一圆弧组成。判断点 (x, y) 是否在其内部,核心是把区域拆解为:中间矩形区 + 四个直角过渡区 + 四个圆弧区。
实际编码中,最常用且鲁棒的方式是基于“最近点距离”思想:先将点映射到矩形的局部坐标系(以矩形左上为原点或以中心为原点),再计算该点到圆角矩形边界的最短距离是否 ≤ 0(即在内部或边界上)。但更高效的做法是分区域裁剪判断:
- 若点落在矩形内但远离所有角(即 x 在
[rx, width - rx]、y 在[ry, height - ry]),则一定在内; - 若点落在某角的“圆角影响区”(例如左上角的
x ∈ [0, rx]且y ∈ [0, ry]),则需判断是否在以(rx, ry)为圆心、半径为rx(假设rx == ry)的四分之一圆内; - 注意:多数 UI 框架(如 Skia、Qt)默认使用等圆角(
rx == ry),若不等(椭圆角),则需用椭圆距离判别,计算开销明显上升。
实操建议:
- 统一使用左上角为原点的坐标系,矩形参数记为
left,top,right,bottom,radius; - 提前做粗筛:若
x right || y bottom,直接返回 false; - 圆角仅影响四个角区域,其余部分按普通矩形处理;
- 若
radius ,退化为普通矩形,跳过所有圆角逻辑。
具体判断逻辑(C++ 实现片段)
以下是一个轻量、无浮点异常风险的实现,假设圆角半径相等(rx == ry == r):
bool pointInRoundRect(double x, double y,
double left, double top,
double right, double bottom,
double r) {
// 粗筛:完全在矩形外
if (x right || y bottom) return false;
<pre class="brush:php;toolbar:false;">// 去除圆角影响后的“内矩形”
double inner_left = left + r;
double inner_right = right - r;
double inner_top = top + r;
double inner_bottom = bottom - r;
// 在内矩形中 → 必然在圆角矩形内
if (x >= inner_left && x = inner_top && y <p>}</p>注意几个易错点:
- 边界处理:用
而非 <code> 保证点恰在圆弧上时返回 true; - 避免 sqrt:用距离平方比较,既快又规避了浮点精度和负数开方问题;
- 圆心坐标不是
(left, top),而是(left + r, top + r)等,容易写反; - 若输入坐标系是中心对齐(如 OpenGL NDC),需先平移到左上对齐再计算。
不等圆角(rx ≠ ry)时怎么处理
当水平圆角半径 rx 和垂直圆角半径 ry 不同时,四个角其实是四段椭圆弧,此时不能简单用圆心距平方比较。
最稳妥的做法是:对每个角,将点坐标做归一化缩放,转成单位圆问题。例如左上角影响区(x ∈ [left, left+rx], y ∈ [top, top+ry]),计算:
double ex = (x - (left + rx)) / rx; double ey = (y - (top + ry)) / ry; return (ex * ex + ey * ey) <p>但要注意:</p>
- 必须确保
rx > 0 && ry > 0,否则除零; - 缩放后判断的是单位圆,不是单位椭圆——这是正确的,因为椭圆方程
((x−cx)/rx)² + ((y−cy)/ry)² ≤ 1就是该区域的数学定义; - 性能比等圆角略低(多两次除法),但仍是常数时间;
- 某些图形库(如 Cairo)支持不等圆角,但 Web CSS 的
border-radius在单值写法下强制等圆角,双值写法才允许rx / ry分离。
常见错误现象与调试技巧
遇到“明明点在圆角内却返回 false”时,优先检查以下几类问题:
- 坐标系混淆:UI 层传入的是屏幕坐标,而函数假设是客户端坐标,未减去窗口偏移;
- 半径超限:当
r > (right - left) / 2或r > (bottom - top) / 2时,圆角已覆盖整个矩形,应截断为最大合法半径(否则inner_left > inner_right导致逻辑崩溃); - 浮点精度陷阱:用
==判断点是否恰好在圆弧上几乎必败,一律改用(ε 取 <code>1e-9即可); - 整数坐标误用:若输入是
int,但函数参数为double,隐式转换一般没问题;但若反过来(函数内部用int运算),会因截断导致左上角区域漏判。
圆角矩形的点判定看似简单,真正难的是在各种边界条件下保持数值稳健性和坐标系一致性。尤其是嵌入到事件分发或 hit-test 流程中时,一个没处理好的 r == 0 分支或坐标翻转,就可能导致点击区域错位。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











