凸多边形的充要条件是所有连续三顶点叉积同号(全≥0或全≤0);需按序遍历每组(p[i−1],p[i],p[i+1])并跨接首尾,允许零叉积但不可正负混杂,建议用sgn函数处理浮点误差。

用叉积符号判断顶点转向是否一致
凸多边形的充要条件是:所有连续三顶点构成的向量叉积同号(全 ≥ 0 或全 ≤ 0),即顶点按顺序(顺时针或逆时针)遍历时,拐向始终一致。C++ 中无需调用几何库,只需手写二维叉积函数 cross 并遍历每组 (p[i-1], p[i], p[i+1])。
注意:输入顶点必须是**按顺序排列的简单多边形**(无自交、首尾不重合),且至少 4 个点;若顶点顺序混乱或含重复点,结果无意义。
- 叉积公式:
cross(a, b, c) = (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x) - 对 i 从 1 到 n−2,检查
cross(p[i-1], p[i], p[i+1]);再补上首尾跨接:i = n−1 时用p[n-2], p[n-1], p[0],i = 0 时用p[n-1], p[0], p[1] - 允许零叉积(三点共线),但不能出现正负混杂;建议用
sign = (val > 0) - (val 统一归为 −1/0/+1,再比对非零值的符号
处理浮点误差与共线点的鲁棒写法
实际坐标常为 double,直接判 == 0 或比较符号易受精度影响。应引入小阈值 EPS = 1e-9,把叉积绝对值小于 EPS 的视为共线(即叉积为 0),仅对 |cross| > EPS 的值记录符号。
常见错误:未跳过共线点就参与符号比较,导致误判;或用 if (cross > 0) 直接分支,漏掉浮点舍入后本该为正却算成负的情况。
- 推荐 sign 函数:
int sgn(double x) { return (x > EPS) ? 1 : (x - 遍历时先计算
s = sgn(cross(...));首次遇到非零s时记下expected_sign = s;后续每个非零s都必须等于expected_sign - 若所有
s全为 0(所有点共线),不是多边形,应提前返回 false
完整可运行的 minimal 示例
以下代码假设顶点存于 vector<pair>></pair>,按逆时针或顺时针给定:
bool isConvex(const vector<pair>>& p) {
int n = p.size();
if (n <p>关键细节:模运算 <code>(i-1+n)%n</code> 安全处理首尾索引;<code>expected != 0</code> 排除所有点共线情形;<code>sgn</code> 必须带 EPS。</p><h3>容易被忽略的边界情况</h3><p>真正卡住人的往往不是算法逻辑,而是输入质量与定义差异:</p><ul>
<li>输入顶点若为顺时针序,叉积全为负——这仍是凸的,代码必须接受负号一致;不要硬性要求“必须为正”</li>
<li>四点中有三点共线(如矩形加一个中点)→ 构成退化四边形,严格数学定义下不算凸多边形(内角含 180°),你的需求是否允许?代码中 <code>sgn==0</code> 被跳过,不影响判断,但需确认业务语义</li>
<li>顶点含重复点(如 <code>p[0] == p[1]</code>)会导致叉积恒为 0,建议在调用前用 <code>unique</code> 预处理,或在叉积前加坐标校验</li>
<li>OpenCV 或 Qt 等库的多边形函数可能默认要求逆时针序,而你的判断函数不关心方向——这点务必和上下游对齐</li>
</ul><p>没做预处理的坐标序列,哪怕只差一个点顺序错位,整个判断就失效。别只盯着叉积公式,先盯住输入是不是真的“有序简单多边形”。</p></pair>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











