圆角矩形由中心矩形与四个象限圆弧组成,关键参数为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 。必须先明确四个核心参数:<code>left、top、right、bottom(矩形外边界),以及圆角半径 r。注意:r 不能超过矩形宽高的一半,否则退化为椭圆或无效形状——实际中建议校验 r ,否则行为未定义。
分区域判断:把平面划成9个逻辑区
圆角矩形可拆解为:4个圆角区域(左上/右上/左下/右下)、4个直边区域(上/下/左/右)、1个中心矩形区域。点 (x, y) 的归属由其相对于「内矩形」(即裁掉圆角后的部分)的位置决定:
内矩形范围是 [left + r, right - r] × [top + r, bottom - r]。
判断流程如下:
- 若
x在[left + r, right - r]且y在[top + r, bottom - r]→ 中心区域,直接命中 - 若
x在[left + r, right - r]但y → 上边直边区域,只需检查 <code>y >= top - 若
x在[left + r, right - r]且y > bottom - r→ 下边直边区域,只需检查y - 若
y在[top + r, bottom - r]但x → 左边直边区域,检查 <code>x >= left - 若
y在[top + r, bottom - r]且x > right - r→ 右边直边区域,检查x - 其余情况属于四个角区域 → 需计算到对应圆心的欧氏距离 ≤
r,例如左上角圆心为(left + r, top + r),距离公式为(x - (left + r))*(x - (left + r)) + (y - (top + r))*(y - (top + r))
C++ 实现要点与易错细节
手写函数时优先用整数或 double 运算,避免浮点比较误差;所有边界判断统一用 ≤ / ≥,不要混用 和 <code> 导致边缘点漏判。常见错误包括:
- 圆心坐标算错:比如左上角圆心误写成
(left, top),正确应为(left + r, top + r) - 没处理
r == 0的退化情形(此时等价于普通矩形),可提前分支优化 - 未考虑坐标系方向:若
y轴向下增长(如 GUI 坐标系),top实际是较小值,但公式不变,只要参数语义一致即可 - 性能敏感场景下,平方距离比较比开方快,坚持用
dx*dx + dy*dy ,而非 <code>sqrt(...)
一个最小可用函数骨架:
立即学习“C++免费学习笔记(深入)”;
bool pointInRoundedRect(double x, double y,
double left, double top,
double right, double bottom,
double r) {
if (r < 0) return false;
r = std::min(r, std::min((right - left)/2, (bottom - top)/2));
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_right && y >= inner_top && y <= inner_bottom)
return true;
if (x >= inner_left && x <= inner_right) {
if (y >= top && y <= inner_top) return true; // top edge
if (y >= inner_bottom && y <= bottom) return true; // bottom edge
return false;
}
if (y >= inner_top && y <= inner_bottom) {
if (x >= left && x <= inner_left) return true; // left edge
if (x >= inner_right && x <= right) return true; // right edge
return false;
}
// corners
double dx, dy;
if (x <= inner_left && y <= inner_top) { // top-left
dx = x - (left + r); dy = y - (top + r);
} else if (x >= inner_right && y <= inner_top) { // top-right
dx = x - (right - r); dy = y - (top + r);
} else if (x <= inner_left && y >= inner_bottom) { // bottom-left
dx = x - (left + r); dy = y - (bottom - r);
} else { // bottom-right
dx = x - (right - r); dy = y - (bottom - r);
}
return dx*dx + dy*dy <= r*r;
}图形库中要注意的兼容性陷阱
不同 GUI 框架对「圆角矩形」的定义可能隐含差异:Qt 的 QPainterPath::addRoundedRect 默认使用 Qt::AbsoluteSize 模式,而 Skia 或 Cairo 可能要求传入 corner radius 分别指定四角。更隐蔽的问题是抗锯齿渲染导致的像素级覆盖偏差——函数返回 true 的点,在光栅化后未必真正着色。如果用于点击检测,建议预留 1px 容差(如将 r 临时增大 0.5),或直接用框架提供的 contains() 方法(如 Qt 的 QRegion.contains()),它内部已处理设备像素比和变换矩阵。自己实现时,若涉及 QTransform 或缩放,必须先将点逆变换回原始坐标系再判断。


















