Appearance
浮点数与精度问题
特殊值:
- +0.0 -0.0
- 在常见的 IEC 60559/IEEE 754 浮点实现中,非零数除以
可能得到 ,对负数开平方等无效运算可能得到 NaN。 NaN与任何数(包括自身)做有序比较或相等比较都返回false,只有!=返回true。
这些行为依赖实现和浮点环境,不能把主动除以零或制造 NaN 当作可移植的分支技巧。应在运算前检查分母、方向向量和定义域,必要时再使用 std::isfinite、std::isinf、std::isnan 检查结果。
- 若问题能用整数解决则不用浮点数
- 除非时限紧张,否则使用
long double - 减少数学库函数的调用
- 进行浮点数比较时,加入容限(误差)eps
下文公式中的
点
向量:
坐标系中一个点对应一个向量,通常使用向量表示一个点。
点积:
点积是一个值:
几何意义:
- 向量的长度:
- 向量的夹角:
,要求 均为非零向量 在 方向上的标量投影: ,要求 ;当 均非零时,它也等于 在 上的向量投影: ,要求 - 向量垂直:
叉积:
向量的叉积仅在
维是一个标量: 维是一个向量:
几何意义:
- 平行四边形面积:
- 向量平行:
- to-left 测试
to-left 测试
判断点 P 在有向直线 AB 左侧/右侧上。
向量逆时针旋转
线段
判断点是否在线段上:
- 点 P 在 AB 所在直线上:
- 点 P 在 AB 之间:
- 若线段包含端点,则
;若只判断开线段内部,才使用
- 若线段包含端点,则
判断两条线段是否相交:
- 若只判断严格相交,则要求点 A 和点 B 在直线 CD 的严格不同侧,且点 C 和点 D 在直线 AB 的严格不同侧。
- 若把端点接触和共线重叠也视为相交,还要分别判断四个端点是否落在另一条线段上;点在线段上的判定使用上一节的闭区间条件。
直线
通常使用点向式表示:直线上的一点 P 和方向向量
求点 A 到直线的距离:
求点 A 在直线上的投影点 B:
两直线交点:
设两条直线分别为
当
参数 inf 或 NaN 区分。
多边形
由点集表示。
- 一般按逆时针顺序
- 不一定满足凸性
- 注意第一个点与最后一个点的处理
多边形的面积:
先定义有向二倍面积
多边形的普通面积为
特别地,三角形的面积:
多边形的方向:
在标准笛卡尔坐标系中,若顶点沿一个不自交多边形的边界依次给出,则:
:逆时针; :顺时针; :退化,不能据此确定方向。
对自交多边形,
判断点是否在多边形内
射线法
从查询点 P 向 BOUNDARY,也可以按题意统一归入内部或外部。
对非边界点,边 AB 仅在以下两种情况之一成立时贡献一次穿越:
且 ; 且 。
这相当于纵坐标区间包含较低端点、排除较高端点,水平边不计数。射线经过普通穿越顶点时贡献一次;经过局部极小点时两条边均贡献,经过局部极大点时两条边均不贡献,因此不会错误改变交点数的奇偶性。穿越次数为奇数时 P 在奇偶填充意义下位于内部,否则位于外部。
回转数法
回转数:闭合曲线绕查询点的有向总圈数。
遵循非零规则:当回转次数为 0 时,点在曲线外部。
- 一种实现方法:计算相邻两边夹角(有方向)的和。
- 另一种实现方法是沿用射线法的半开规则:向上穿越贡献
,向下穿越贡献 。这种写法避免了反三角函数;只有在坐标为整数、叉积使用足够宽的整数类型且中间运算不溢出时,方向判定才没有浮点误差。浮点坐标仍需使用稳健的误差比较。
对简单多边形,奇偶规则与非零回转数规则给出相同的内外结果;对自交多边形,两者分别对应奇偶填充和非零填充,结果可能不同。
判断点是否在凸多边形内
次 to-left 测试 。 二分
。
上述方法要求多边形凸、非退化,且顶点按同一方向沿边界给出;二分实现还需单独约定点落在边或顶点上的返回结果。
