欧拉公式 和 计算几何模板
欧拉公式
学习向量旋转的时候用到的,在百度知道查到了公式的证明过程,做个记录。
证明过程
将\(y=e^x,y=\sin x,y=\cos x\)用幂级数展开,有
\[e^x=\exp(x)=1+{x}+\frac{x^2}{2!}+\frac{x^3}{3!}+\frac{x^4}{4!}+\dots+\frac{x^n}{n}+\dots \\
\sin x=x-\frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+\dots+(-1)^{k-1}\frac{x^{2k-1}}{(2k-1)!}+\dots \\
\cos x=1-\frac{x^2}{2!}+\frac{x^4}{4!}-\frac{x^6}{6!}+\dots+(-1)^k\frac{x^{2k}}{(2k)!}+\dots
\]
将式中的\(x\)换为\(ix\),就得到了
\[e^{ix}=\cos x+i \sin x
\]
将等式里的\(x\)替换为\(-x\),得到
\[e^{-ix}=\cos x-i \sin x
\]
然后采用两式相加减的方法得到
\[\sin x=\frac{e^{ix}-e^{-ix}}{2i} \\
\cos x=\frac{e^{ix}+e^{-ix}}{2} \\
\tan x=\frac{e^{ix}-e^{-ix}}{ie^{ix}+ie^{-ix}}
\]
此时三角函数定义域已推广至整个复数集。
辅助内容
幂级数
\[c_0+c_1x+c_2x^2+\dots+c_nx^n+\dots=\sum_{n=0}^{\infty}c_nx^n \\
c_0+c_1(x-a)+c_2(x-a)^2+\dots+c_n(x-a)^n+\dots=\sum_{n=0}^{\infty}c_n(x-a)^n
\]
他们的各项都是正整数幂的幂级数,其中\(c_0,c_1,\dots,c_n,\dots\)以及\(a\)都是常数,这种级数称为幂级数。
泰勒展开式(幂级数展开法)
\[f(x)=f(a)+f'(a)(x-a)+\frac{f''(a)}{2!}(x-a)^2+\dots+\frac{f^{(n)}(a)}{n!}(x-a)^n+R_n(x)
\]
实用幂级数
\[e^x=1+x+\frac{x^2}{2!}+\frac{x^3}{3!}+\dots+\frac{x^n}{n!}+\dots \\
\ln(x+1)=x-\frac{x^2}{2}+\frac{x^3}{3}+\dots+(-1)^{n-1}\frac{x^n}{n}+\dots
\]
向量基础
const double eps=1e-10;
int dcmp(double x)
{
if(fabs(x)<eps)
return 0;
else
return x<0?-1:1;
}
struct Point
{
double x,y;
Point(double x=0,double y=0)
:x(x),y(y){}
bool operator<(co Point&rhs)co // edit 1
{
return dcmp(x-rhs.x)?x<rhs.x:y<rhs.y;
}
bool operator==(co Point&rhs)co
{
return dcmp(x-rhs.x)==0&&dcmp(y-rhs.y)==0;
}
double angle()
{
return atan2(y,x);
}
};
typedef Point Vector;
Vector operator+(Vector A,Vector B)
{
return Vector(A.x+B.x,A.y+B.y);
}
Vector operator-(Point A,Point B)
{
return Vector(A.x-B.x,A.y-B.y);
}
Vector operator*(Vector A,double p)
{
return Vector(A.x*p,A.y*p);
}
Vector operator/(Vector A,double p)
{
return Vector(A.x/p,A.y/p);
}
double Dot(Vector A,Vector B)
{
return A.x*B.x+A.y*B.y;
}
double Length(Vector A)
{
return sqrt(Dot(A,A));
}
double Angle(Vector A,Vector B)
{
return acos(Dot(A,B)/Length(A)/Length(B));
}
double Cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
double Area2(Point A,Point B,Point C)
{
return Cross(B-A,C-A);
}
Vector Rotate(Vector A,double rad)
{
return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
Vector Normal(Vector A)
{
double L=Length(A);
return Vector(-A.y/L,A.x/L);
}
Point LineLineIntersection(Point P,Vector v,Point Q,Vector w)
{
Vector u=P-Q;
double t=Cross(w,u)/Cross(v,w);
return P+v*t;
}
double DistanceToLine(Point P,Point A,Point B)
{
Vector v1=B-A,v2=P-A;
return fabs(Cross(v1,v2))/Length(v1);
}
double DistanceToSegment(Point P,Point A,Point B)
{
if(A==B)
return Length(P-A);
Vector v1=B-A,v2=P-A,v3=P-B;
if(dcmp(Dot(v1,v2))<0)
return Length(v2);
if(dcmp(Dot(v1,v3))>0)
return Length(v3);
return DistanceToLine(P,A,B);
}
Point PointLineProjection(Point P,Point A,Point B)
{
Vector v=B-A;
return A+v*(Dot(v,P-A)/Dot(v,v));
}
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
{
double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),
c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}
bool OnSegment(Point p,Point a1,Point a2)
{
return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
}
double PolygonArea(Point*p,int n)
{
double area=0;
for(int i=1;i<n-1;++i)
area+=Cross(p[i]-p[0],p[i+1]-p[0]);
return area/2;
}
凸包(水平序)
按\(x\)排序后始终找前进方向右边的点,用个栈维护,上凸壳下凸壳分别做一遍。
时间复杂度是排序的\(O(n \log n)\)
int ConvexHull(Point*p,int n,Point*ch)
{
sort(p,p+n);
int m=0;
for(int i=0;i<n;++i)
{
while(m>1&&dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0)
--m;
ch[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;--i)
{
while(m>k&&dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0)
--m;
ch[m++]=p[i];
}
if(n>1)
m--;
return m;
}
半平面交
atan2(y,x)的值域是\((-\pi,\pi]\),返回相当于\(x+yi\)的幅角。
半平面交维护的是点集,用双端队列维护。时间复杂度为排序的\(O(n \log n)\)
struct Line
{
Point P;
Vector v;
Line(Point P=0,Vector v=0)
:P(P),v(v){}
double angle()co
{
return atan2(v.y,v.x);
}
bool operator<(co Line&rhs)co
{
return angle()<rhs.angle();
}
};
bool OnLeft(co Line&L,co Point&p)
{
return Cross(L.v,p-L.P)>0;
}
Point LineLineIntersection(co Line&a,co Line&b)
{
Vector u=a.P-b.P;
double t=Cross(b.v,u)/Cross(a.v,b.v);
return a.P+a.v*t;
}
co double INF=1e8;
co double eps=1e-6;
vector<Point>HalfplaneIntersection(vector<Line>L)
{
int n=L.size();
sort(L.begin(),L.end());
int first,last;
vector<Point>p(n);
vector<Line>q(n);
vector<Point>ans;
q[first=last=0]=L[0];
for(int i=1;i<n;++i)
{
while(first<last&&!OnLeft(L[i],p[last-1]))
--last;
while(first<last&&!OnLeft(L[i],p[first]))
++first;
q[++last]=L[i];
if(fabs(Cross(q[last].v,q[last-1].v))<eps)
{
--last;
if(OnLeft(q[last],L[i].P))
q[last]=L[i];
}
if(first<last)
p[last-1]=LineLineIntersection(q[last-1],q[last]);
}
while(first<last&&!OnLeft(q[first],p[last-1]))
--last;
if(last-first<=1)
return ans;
p[last]=LineLineIntersection(q[last],q[first]);
for(int i=first;i<=last;++i)
ans.push_back(p[i]);
return ans;
}
圆
struct Circle
{
Point c;
double r;
Circle(Point c=0,double r=0)
:c(c),r(r){}
Point point(double a)
{
return Point(c.x+cos(a)*r,c.y+sin(a)*r);
}
};
int LineCircleIntersection(Line L,Circle C,double&t1,double&t2,vector<Point>&sol)
{
double a=L.v.x,b=L.p.x-C.c.x,c=L.v.y,d=L.p.y-C.c.y;
double e=a*a+c*c,f=2*(a*b+c*d),g=b*b+d*d-C.r*C.r;
double delta=f*f-4*e*g;
if(dcmp(delta)<0)
return 0;
if(dcmp(delta)==0)
{
t1=t2=-f/(2*e);
sol.push_back(L.point(t1));
return 1;
}
t1=(-f-sqrt(delta))/(2*e);
t2=(-f+sqrt(delta))/(2*e);
sol.push_back(L.point(t1));
sol.push_back(L.point(t2));
return 2;
}
int CircleCircleIntersection(Circle C1,Circle C2,vector<Point>&sol)
{
double d=Length(C1.c-C2.c);
if(dcmp(d)==0)
{
if(dcmp(C1.r-C2.r)==0)
return -1;
return 0;
}
if(dcmp(C1.r+C2.r-d)<0)
return 0;
if(dcmp(fabs(C1.r-C2.r)-d)>0)
return 0;
double a=(C2.c-C1.c).angle();
double da=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));
Point p1=C1.point(a-da),p2=C1.point(a+da);
sol.push_back(p1);
if(p1==p2)
return 1;
sol.push_back(p2);
return 2;
}
co double PI=acos(-1);
int PointCircleTangent(Point p,Circle C,vector<Vector>&sol)
{
Vector u=C.c-p;
double dist=Length(u);
if(dcmp(dist-C.r)<0)
return 0;
if(dcmp(dist-C.r)==0)
{
sol.push_back(Rotate(u,PI/2));
return 1;
}
double ang=asin(C.r/dist);
sol.push_back(Rotate(u,-ang));
sol.push_back(Rotate(u,ang));
return 2;
}
int CircleCircleTangent(Circle A,Circle B,vector<pair<Point,Point> >&sol)
{
int cnt=0;
if(dcmp(A.r-B.r)<0) // notice the result here
swap(A,B);
double d=Length(A.c-B.c);
double rdiff=A.r-B.r;
double rsum=A.r+B.r;
if(dcmp(d-rdiff)<0)
return 0;
double base=(B.c-A.c).angle();
if(dcmp(d)==0&&dcmp(A.r-B.r)==0)
return -1;
if(dcmp(d-rdiff)==0)
{
sol.push_back(make_pair(A.point(base),B.point(base)));
++cnt;
return 1;
}
double ang=acos((A.r-B.r)/d);
sol.push_back(make_pair(A.point(base+ang),B.point(base+ang)));
++cnt;
sol.push_back(make_pair(A.point(base-ang),B.point(base-ang)));
++cnt;
if(dcmp(d-rsum)==0)
{
sol.push_back(make_pair(A.point(base),B.point(base+PI)));
++cnt;
}
else if(dcmp(d-rsum)>0)
{
double ang=acos((A.r+B.r)/d);
sol.push_back(make_pair(A.point(base+ang),B.point(base+ang+PI)));
++cnt;
sol.push_back(make_pair(A.point(base-ang),B.point(base-ang+PI)));
++cnt;
}
return cnt;
}
静渊以有谋,疏通而知事。
浙公网安备 33010602011771号