圆角矩形由中心矩形与四个象限圆弧组成,关键参数为left、top、right、bottom及radius(需满足r≤min((right−left)/2,(bottom−top)/2));判断点(x,y)时先验是否在外包围矩形内,再按所在象限计算平移后坐标(dx,dy),通过dx²+dy²≤r²判定是否落入对应圆角区,radius=0时退化为普通矩形判断。

圆角矩形的数学定义和关键分区域逻辑
带圆角的矩形本质是「中心矩形 + 四个四分之一圆弧」,判断点 (x, y) 是否在内,不能直接套用普通矩形的 x_min 。必须先识别点落在哪个区域:是中心矩形区、某条直边延伸区,还是某个圆角区。
设矩形左上角为 (x0, y0),宽 w、高 h,圆角半径 r(需满足 r ,否则圆角会重叠)。四个圆心坐标分别是:<code>(x0 + r, y0 + r)(左上)、(x0 + w - r, y0 + r)(右上)、(x0 + r, y0 + h - r)(左下)、(x0 + w - r, y0 + h - r)(右下)。
- 若
x在[x0 + r, x0 + w - r]且y在[y0 + r, y0 + h - r]→ 属于中心矩形区,直接判定点在内 - 若
x在[x0, x0 + r)且y在[y0, y0 + r)→ 进入左上圆角区,需计算到左上圆心的距离 ≤r - 类似地,对右上、左下、右下三个角分别做距离判断
- 其余情况(如
x在[x0 + r, x0 + w - r]但y在[y0, y0 + r))→ 属于上边直边区,只需检查y >= y0且x在横向上合法(已满足),无需额外距离计算
标准实现:用 if-else 分块处理,避免浮点误差累积
不要试图用一个表达式硬写,分支清晰反而更易读、易调试、易覆盖边界。尤其注意:圆角区判断必须用「距离平方 ≤ r²」,避免 sqrt 引入精度误差和性能开销。
bool pointInRoundedRect(double x, double y,
double x0, double y0,
double w, double h,
double r) {
// 先快速排除完全在外的点
if (x < x0 || x > x0 + w || y < y0 || y > y0 + h) return false;
<pre class='brush:php;toolbar:false;'>// 中心矩形区(不含圆角部分)
if (x >= x0 + r && x <= x0 + w - r &&
y >= y0 + r && y <= y0 + h - r) {
return true;
}
// 上边区域:y ∈ [y0, y0 + r),x ∈ [x0 + r, x0 + w - r]
if (y >= y0 && y < y0 + r) {
return x >= x0 && x <= x0 + w;
}
// 下边区域:y ∈ [y0 + h - r, y0 + h]
if (y > y0 + h - r && y <= y0 + h) {
return x >= x0 && x <= x0 + w;
}
// 左边区域:x ∈ [x0, x0 + r),y ∈ [y0 + r, y0 + h - r]
if (x >= x0 && x < x0 + r) {
return y >= y0 && y <= y0 + h;
}
// 右边区域:x ∈ [x0 + w - r, x0 + w]
if (x > x0 + w - r && x <= x0 + w) {
return y >= y0 && y <= y0 + h;
}
// 剩余四角 —— 必须用距离平方判断
double dx, dy, distSq;
// 左上角
if (x <= x0 + r && y <= y0 + r) {
dx = x - (x0 + r);
dy = y - (y0 + r);
distSq = dx * dx + dy * dy;
return distSq <= r * r;
}
// 右上角
if (x >= x0 + w - r && y <= y0 + r) {
dx = x - (x0 + w - r);
dy = y - (y0 + r);
distSq = dx * dx + dy * dy;
return distSq <= r * r;
}
// 左下角
if (x <= x0 + r && y >= y0 + h - r) {
dx = x - (x0 + r);
dy = y - (y0 + h - r);
distSq = dx * dx + dy * dy;
return distSq <= r * r;
}
// 右下角
dx = x - (x0 + w - r);
dy = y - (y0 + h - r);
distSq = dx * dx + dy * dy;
return distSq <= r * r;}
立即学习“C++免费学习笔记(深入)”;
容易被忽略的边界细节
很多实现漏掉「点恰好落在圆角与直边交界线」的情况,比如 x == x0 + r && y == y0 —— 这个点既在上边直边,又在左上圆角弧上,必须被包含。上面代码中各区间用的是「≤」和「
-
r为 0 时,应退化为普通矩形;测试时务必验证r == 0路径是否仍正确 - 若输入坐标或尺寸含
NaN或无穷大,函数行为未定义;生产环境建议前置校验 - 当
r > min(w/2, h/2)时,圆角实际会重叠,此时几何已不是标准圆角矩形;函数不负责校验该条件,调用方需保证输入合法 - 使用
double是为了兼顾精度,但如果业务场景全是整数坐标,可用int并把r * r改为整型乘法,避免隐式转换
性能敏感场景下的优化提示
如果每帧要判断成千上万个点,可考虑预计算四个圆心坐标和 r_sq = r * r,避免重复运算;但分支结构本身已是 O(1),进一步优化空间有限。真正瓶颈往往不在这里,而在缓存友好性——把矩形参数打包成结构体(如 struct RoundedRect),并让批量点判断循环能顺序访问内存,比微调单次判断更重要。
另外,若所有圆角矩形的 r 都相同,可将距离平方比较展开为具体数值,减少一次乘法;但这种优化仅在极端场景下有意义,通常得不偿失。


















