浮点精度
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
int sgn(double x) {
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
return 1;
}
s g n 三 态 函 数 用 于 减 少 浮 点 的 精 度 问 题 sgn三态函数用于减少浮点的精度问题 sgn三态函数用于减少浮点的精度问题
叉积
// 叉积
double operator ^ (const Point &b)const {
return x*b.y - y*b.x;
}
定义
向量叉积:
a
×
b
=
a
b
s
i
n
(
θ
)
a × b = absin(\theta)
a×b=absin(θ)
模长:
∣
a
×
b
∣
=
∣
a
∣
∣
b
∣
s
i
n
(
θ
)
|a × b| = |a||b|sin(\theta)
∣a×b∣=∣a∣∣b∣sin(θ)
方向:
θ
的
方
向
是
从
a
→
b
方
向
的
夹
角
。
\theta 的方向是从a \to b方向的夹角。
θ的方向是从a→b方向的夹角。
叉
积
的
方
向
满
足
a
→
b
的
右
手
法
则
,
即
与
a
,
b
构
成
的
平
面
垂
直
。
叉积的方向满足a\to b的右手法则,即与a,b构成的平面垂直。
叉积的方向满足a→b的右手法则,即与a,b构成的平面垂直。
性质
1.
∣
a
×
b
∣
=
a
和
b
构
成
的
平
行
四
边
形
面
积
1.|a × b| = a和b构成的平行四边形面积
1.∣a×b∣=a和b构成的平行四边形面积
如
上
图
因
为
∣
a
×
b
∣
=
∣
a
∣
∣
b
∣
s
i
n
(
θ
)
;
∣
a
∣
s
i
n
(
θ
)
=
h
如上图因为|a × b| = |a||b|sin(\theta) ;|a|sin(\theta) = h
如上图因为∣a×b∣=∣a∣∣b∣sin(θ);∣a∣sin(θ)=h
∣
a
×
b
∣
=
h
∣
b
∣
=
S
A
B
C
D
|a × b| = h|b| = S_{ABCD}
∣a×b∣=h∣b∣=SABCD
2.
叉
积
判
断
线
段
拐
向
2.叉积判断线段拐向
2.叉积判断线段拐向
a
×
b
=
=
0
:
a
和
b
平
行
a × b ==0 : a和b平行
a×b==0:a和b平行
a
×
b
>
0
:
b
在
a
的
逆
时
针
方
向
(
0
<
θ
≤
10
8
。
)
a × b > 0 : b在a的逆时针方向(0< \theta \leq 108^。)
a×b>0:b在a的逆时针方向(0<θ≤108。)
a
×
b
<
0
:
b
在
a
的
顺
时
针
方
向
(
0
<
θ
≤
10
8
。
)
a × b < 0 : b在a的顺时针方向(0< \theta \leq 108^。)
a×b<0:b在a的顺时针方向(0<θ≤108。)
3.
判
断
点
在
多
边
形
内
3.判断点在多边形内
3.判断点在多边形内
4.
判
断
两
直
线
相
交
(
跨
立
实
验
)
4.判断两直线相交(跨立实验)
4.判断两直线相交(跨立实验)
5.
极
角
排
序
5.极角排序
5.极角排序
点积
// 点积
double operator * (const Point &b)const {
return x*b.x + y*b.y;
}
定义
a
∙
b
=
∣
a
∣
∣
b
∣
c
o
s
(
θ
)
a \bullet b = |a||b|cos(\theta)
a∙b=∣a∣∣b∣cos(θ)
a
∙
b
=
∣
a
∣
∣
b
∣
c
o
s
(
θ
)
=
d
∣
a
∣
;
d
是
b
在
a
上
的
投
影
a \bullet b = |a||b|cos(\theta) = d|a|;d是b在a上的投影
a∙b=∣a∣∣b∣cos(θ)=d∣a∣;d是b在a上的投影
计算 pa 和 pb 的夹角
// 测试LightOJ1203
double rad(Point a,Point b) {
Point p = *this;
return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
}
x
=
p
→
a
;
y
=
p
→
b
x = p \to a;y = p \to b
x=p→a;y=p→b
x
×
y
=
∣
x
∣
∣
y
∣
s
i
n
(
θ
)
x × y = |x||y|sin(\theta)
x×y=∣x∣∣y∣sin(θ)
x
∙
y
=
∣
x
∣
∣
y
∣
c
o
s
(
θ
)
x\bullet y = |x||y|cos(\theta)
x∙y=∣x∣∣y∣cos(θ)
t
a
n
(
θ
)
=
x
×
y
x
∙
y
tan(\theta) = \frac{x × y}{x \bullet y}
tan(θ)=x∙yx×y
化为长度为r的向量
Point trunc(double r) {
double l = len();
if(!sgn(l)) return *this;
r /= l;
return Point(x*r,y*r);
}
用途
已知直线向量。求出直线上任意一点
如
图
已
知
点
A
(
x
1
,
y
1
)
,
C
(
x
2
,
y
2
)
。
想
要
计
算
出
距
离
点
A
长
度
为
r
的
B
点
坐
标
如图已知点A(x1,y1),C(x2,y2)。想要计算出距离点A长度为r的B点坐标
如图已知点A(x1,y1),C(x2,y2)。想要计算出距离点A长度为r的B点坐标
B
=
A
+
(
C
−
A
)
.
t
r
u
n
c
(
r
)
B = A + (C-A).trunc(r)
B=A+(C−A).trunc(r)
向量绕点P旋转angle
公
式
已
知
点
A
(
x
,
y
)
,
绕
点
P
(
a
,
b
)
逆
时
针
转
θ
得
到
B
(
x
1
,
y
1
)
公式已知点A(x,y),绕点P(a,b)逆时针转\theta 得到B(x1,y1)
公式已知点A(x,y),绕点P(a,b)逆时针转θ得到B(x1,y1)
x
1
=
a
+
x
∗
c
o
s
(
θ
)
−
y
∗
s
i
n
(
θ
)
x1 = a + x*cos(\theta)-y*sin(\theta)
x1=a+x∗cos(θ)−y∗sin(θ)
y
1
=
b
+
x
∗
s
i
n
(
θ
)
+
y
∗
c
o
s
(
θ
)
y1 = b + x*sin(\theta)+y*cos(\theta)
y1=b+x∗sin(θ)+y∗cos(θ)
Point rotate(Point p,double angle) {
Point v = (*this) - p;
double c = cos(angle),s = sin(angle);
return Point(p.x + v.x*c - v.y*s,p.y+v.x*s + v.y*c);
}
Code
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
int sgn(double x) {
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
return 1;
}
inline double sqr(double x) {return x*x;}
struct Point {
double x,y;
Point() {}
Point(double _x,double _y) {
x = _x;
y = _y;
}
void input() {
scanf("%lf%lf",&x,&y);
}
void output() {
printf("%.2f %.2f\n",x,y);
}
bool operator == (Point b)const {
return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
}
bool operator < (Point b)const {
return sgn(x-b.x) == 0 ? sgn(y-b.y)<0 : sgn(x-b.x)<0;
}
Point operator - (const Point &b)const {
return Point(x-b.x,y-b.y);
}
// 叉积
double operator ^ (const Point &b)const {
return x*b.y - y*b.x;
}
// 点积
double operator * (const Point &b)const {
return x*b.x + y*b.y;
}
// 返回长度
double len() {
return hypot(x,y); // 库函数
}
//
double len2() {
return x*x + y*y;
}
double distance(Point p) {
return hypot(x-p.x,y-p.y);
}
Point operator + (const Point &b)const {
return Point(x+b.x,y+b.y);
}
Point operator * (const double &k)const {
return Point(x*k,y*k);
}
Point operator / (const double &k)const {
return Point(x/k,y/k);
}
// 计算 pa 和 pb 的夹角
// 测试LightOJ1203
double rad(Point a,Point b) {
Point p = *this;
return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
}
// 化为长度为r的向量
Point trunc(double r) {
double l = len();
if(!sgn(l)) return *this;
r /= l;
return Point(x*r,y*r);
}
// 逆时针旋转90度(绕原点)
Point rotleft() {
return Point(-y,x);
}
// 顺时针旋转90度(绕原点)
Point rotright() {
return Point(y,-x);
}
// 绕着p点逆时针旋转angle
Point rotate(Point p,double angle) {
Point v = (*this) - p;
double c = cos(angle),s = sin(angle);
return Point(p.x + v.x*c - v.y*s,p.y+v.x*s + v.y*c);
}
};
int main()
{
}