ACM几何基础篇

本文介绍了计算几何的基础知识,包括点与向量、线、多边形和圆的定义与相关运算。讨论了浮点误差处理、常用函数以及解决浮点数相等判断的方法。此外,还涵盖了在ICPC竞赛中计算几何的应用特点。
摘要由CSDN通过智能技术生成

文章目录

1 前言

1.1 生产生活

随着科学技术的飞速发展及计算机在国民经济各个领域中的普遍运用,计算机辅助设计,即CAD越来越为人们所重视。当前的CAD工作中,计算机远远不只是一种高效的计算工具,它已成为人们进行创造性设计活动的得力助手甚至参谋。计算几何作为CAD的基础理论之一,主要研究内容是几何形体的数学描述和计算机表述;它同计算机辅助几何设计,即CAGD有着十分密切的关系。而CAGD是由微分几何、代数几何、数值计算、逼近论、拓扑学以及数控技术等形成的一门新兴边缘学科,其主要研究对象和内容是对自由形曲线、曲面的数学描述、设计、分析及图形的显示、处理等。

1.2 ICPC竞赛

  • 在竞赛中,计算几何相比于其他部分来说是比较独立的

  • 曾出现过其与图论和动态规划相结合的题目,计算几何与其他的知识点很少有过多的结合

  • 计算几何的题目难度不会很大,但也永远不会成为最水的题

  • 计算几何题目具有代码量大、特殊情况多。精度问题难以控制等特点

2 准备知识

2.1 头文件及函数及常量

#include <cstdio>
#include <cmath>

using namespace std;

const double pi = acos(-1.0);
const double inf = 1e100;
const double eps = 1e-6;
int sgn(double d){
   
    if(fabs(d) < eps)
        return 0;
    if(d > 0)
        return 1;
    return -1;
}

int main() {
   
    double x = 1.49999;
    int fx = floor(x);//向下取整函数
    int cx = ceil(x);//向上取整函数
    int rx = round(x);//四舍五入函数
    printf("%f %d %d %d\n", x, fx, cx, rx);
    //输出结果 1.499990 1 2 1
    return  0 ;
}

2.2 浮点误差

计算几何中一般来说使用 d o u b l e double double类型比较频繁,该用实数是就用 d o u b l e double double f l o a t float float容易失去精度

d o u b l e double double类型读入时应用 % l f \%lf %lf占位符

而输出时应用 % f \%f %f占位符

2.2.1 计算误差

尽量少用三角函数、除法、开方、求幂、取对数运算

  • 尽量把公式整理成使用的以上操作最少的形式

  • 1.0 / 2.0 ∗ 3.0 / 4.0 ∗ 5.0 = ( 1.0 ∗ 3.0 ∗ 5.0 ) / ( 2.0 ∗ 4.0 ) 1.0/2.0*3.0/4.0*5.0 = (1.0*3.0*5.0)/(2.0*4.0) 1.0/2.03.0/4.05.0=(1.03.05.0)/(2.04.0)

  • 在不溢出的情况下将除式比较转化为乘式比较

  • a b > c ⇔ a > b c \frac {a}{b} > c \Leftrightarrow a > bc ba>ca>bc

在使用除法、开根号、和三角函数的时候,我们要考虑由浮点误差运算产生的代价

2.2.2 判等

不要直接用等号判断浮点数是否相等!
不要直接用等号判断浮点数是否相等!
不要直接用等号判断浮点数是否相等!

同样的一个数 1.5 1.5 1.5如果从不同的途径计算得来,它们的储存方式可能会是 a = 1.4999999 a = 1.4999999 a=1.4999999 b = 1.5000001 b = 1.5000001 b=1.5000001,此时使用 a = = b a == b a==b判断将返回 f a l s e false false

2.2.2.1 解决方案 1 误差判别法

借助 ε \varepsilon ε也就是上面定义的常量eps

const double eps = 1e-9;
int dcmp(double x, double y){
   
    if(fabs(x - y) < eps)
        return 0;
    if(x > y)
        return 1;
    return -1;
}
2.2.2.2 解决方案 2 化浮为整

在不溢出整数范围的情况下,可以通过乘上 1 0 k 10 ^ k 10k转化为整数运算,最后再将结果转化为浮点数输出

2.2.3 负零

输出时一定要小心不要输出 − 0 -0 0,比如

double a = -0.000001;
printf("%.4f", a);

2.2.4 反三角函数

使用反三角函数时,要注意定义域的范围,比如,经过计算 x = 1.000001

double x = 1.000001;
double acx = acos(x);
//可能会返回runtime error

//此时我们可以加一句判断
double x = 1.000001;
if(fabs(x - 1.0) < eps || fabs(x + 1.0) < eps)
	x = round(x);
double acx = acos(x);

2.3 模板总结

#include <cstdio>
#include <cmath>

using namespace std;

const double pi = acos(-1.0);
const double inf = 1e100;
const double eps = 1e-6;
int sgn(double d){
   
    if(fabs(d) < eps)
        return 0;
    if(d > 0)
        return 1;
    return -1;
}
int dcmp(double x, double y){
   
    if(fabs(x - y) < eps)
        return 0;
    if(x > y)
        return 1;
    return -1;
}
int main() {
   
    double x = 1.49999;
    int fx = floor(x);//向下取整函数
    int cx = ceil(x);//向上取整函数
    int rx = round(x);//四舍五入函数
    printf("%f %d %d %d\n", x, fx, cx, rx);
    //输出结果 1.499990 1 2 1
    return  0 ;
}

3 点与向量

3.2 相关定义

3.1.1 点的定义

二维平面下的点的表示只需要两个实数,即横坐标与纵坐标即可

struct Point{
   
    double x, y;
    Point(double x = 0, double y = 0):x(x),y(y){
   }
};

3.1.2 向量的定义

  • 既有大小又有方向的量叫做向量
  • 在计算机中我们常用坐标表示

这样看来,向量这个结构体貌似与点没有任何区别,因此我们可以

typedef Point Vector;

3.2 运算

3.2.1 加减乘除

3.2.1.1 加法运算
  • 点与点之间的加法运算没有意义

  • 点与向量相加得到另一个点

  • 向量与向量相加得到另外一个向量

Vector operator + (Vector A, Vector B){
   
    return Vector(A.x+B.x, A.y+B.y);
}
3.2.1.2 减法运算

两个点之间作差将得到一个向量, A − B A - B AB将得到由 B B B指向 A A A的向量 B A ⃗ \vec{BA} BA

Vector operator - (Point A, Point B){
   
    return Vector(A.x-B.x, A.y-B.y);
}
3.2.1.3 乘法运算

向量与实数相乘得到等比例缩放的向量

Vector operator * (Vector A, double p){
   
    return Vector(A.x*p, A.y*p);
}
3.2.1.4 除法运算

向量与实数相除得到等比例缩放的向量

Vector operator / (Vector A, double p
  • 39
    点赞
  • 147
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
ACM 很全的计算几何模板 基础部分 1.几何公式 5 1.1三角形 5 1.2四边形 5 1.3正n边形 5 1.4圆 5 1.5棱柱 6 1.6棱锥 6 1.7棱台 6 1.8圆柱 6 1.9圆锥 6 1.10圆台 7 1.11球 7 1.12球台 7 1.13球扇形 7 2.直线与线段 7 2.0预备函数 7 2.1判三点是否共线 8 2.2判点是否在线段上 9 2.3判断两点在线段的同一侧 9 2.4判断两点是否在线段的异侧 9 2.5求点关于直线的对称点 10 2.7判断两线段是否相交 10 2.7.1常用版 10 2.7.2不常用版 11 2.8 求两条直线的交点 11 2.9点到直线的最近距离 12 2.10点到线段的最近距离 12 3.多边形 12 3.0 预备浮点函数 12 3.1判定是否是凸多边形 13 3.2判定点是否在多边形内 14 3.3 判定一条线段是否在一个任意多边形内 15 4. 三角形 16 4.0预备函数 16 4.1求三角形的外心 17 4.2求三角形内心 17 4.3求三角形垂心 17 5. 圆 18 5.0预备函数 18 5.1判定直线是否与圆相交 19 5.2判定线段与圆相交 19 5.3判圆和圆相交 19 5.4计算圆上到点p最近点 19 5.5计算直线与圆的交点 20 5.6计算两个圆的交点 20 6. 球面 21 6.0给出地球经度纬度,计算圆心角 21 6.1已知经纬度,计算地球上两点直线距离 21 6.2已知经纬度,计算地球上两点球面距离 21 7. 三维几何的若干模板 22 7.0预备函数 22 7.1判定三点是否共线 23 7.2判定四点是否共面 23 7.1判定点是否在线段上 23 7.2判断点是否在空间三角形上 24 7.3判断两点是否在线段同侧 24 7.4判断两点是否在线段异侧 25 7.5判断两点是否在平面同侧 25 7.6判断两点是否在平面异侧 25 7.7判断两空间直线是否平行 25 7.8判断两平面是否平行 26 7.9判断直线是否与平面平行 26 7.10判断两直线是否垂直 26 7.11判断两平面是否垂直 26 7.12判断两条空间线段是否相交 27 7.13判断线段是否与空间三角形相交 27 7.14计算两条直线的交点 28 7.15计算直线与平面的交点 28 7.16计算两平面的交线 29 7.17点到直线的距离 29 7.18 计算点到平面的距离 29 7.19计算直线到直线的距离 30 7.20空间两直线夹角的cos值 30 7.21两平面夹角的cos值 30 7.22直线与平面夹角sin值 31 1.最远曼哈顿距离 31 2. 最近点对 32 3. 最近点对 34 4. 最小包围圆 36 5. 求两个圆的交点 39 6. 求三角形外接圆圆心 40 7. 求凸包 42 8.凸包卡壳旋转求出所有对踵点、最远点对 44 9. 凸包+旋转卡壳求平面面积最大三角 47 10. Pick定理 50 11. 求多边形面积和重心 51 12. 判断一个简单多边形是否有核 52 13. 模拟退火 54 14. 六边形坐标系 56 15. 用一个给定半径的圆覆盖最多的点 60 16. 不等大的圆的圆弧表示 62 17. 矩形面积并 62 18. 矩形的周长并 66 19. 最近圆对 70 20. 求两个圆的面积交 74
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值