计算几何 - 二维几何(模板)

几何意义:
  向量的点积(a · b )a · b = |a||b| cos {\cos\emptyset } ,若 cos {\cos\emptyset } 为正,两向量之间的夹角为锐角;为负,两向量夹角为钝角;为量,两向量夹角为直角。(ba 方向上的投影)。
  向量的叉积(a × b )a · b = |a||b| sin {\sin\emptyset } ,数值上表示 ab构成的平行四边形的面积。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int Max_n=1e5+10;
const double eps=1e-10;
const double pi=acos(-1.0);

inline int sign(const double &x){//判断一个数(double)的正负
    if(x>eps) return 1;
    if(x<-eps) return -1;
    return 0;
}

struct Point{//定义一个向量的类型(点可以看做另一个端点(0,0)的向量)
    double x,y;
    //Point(){}
    Point(double _x=0,double _y=0):x(_x),y(_y){}//构造函数
    Point operator +(const Point &P) const{//向量减
        return Point(x+P.x,y+P.y);//使用构造函数
    }
    Point operator -(const Point &P) const {//向量减
        return Point(x-P.x,y-P.y);
    }
    double operator ^(const Point &P) const{//向量叉积
        return x*P.y-y*P.x;
    }
    Point operator *(const double &val) const{//向量乘实数
        return Point(x*val,y*val);
    }
    Point operator /(const double &val) const{//向量除以实数
        return Point(x/val,y/val);
    }
    bool operator < (const Point &P) const {//重载小于运算符(排序使用)
        return x<P.x||(x==P.x&&y<P.y);
    }
    bool operator == (const Point &P) const {
        return sign(x-P.x)==0&&sign(y-P.y)==0;
    }
};

///基本运算
//计算两点间距离
inline double Dis(const Point &p0,const Point &pi){//|p0pi|
    return sqrt((p0.x-pi.x)*(p0.x-pi.x)+(p0.y-pi.y)*(p0.y-pi.y));
}
//计算两个向量的叉积
inline double Mul(const Point &p0,const Point &p1,const Point &p2){//叉积 p0p1,p0p2
    return (p1-p0)^(p2-p0);//使用向量减和叉积
}
//计算两个向量的点积
inline double Dot(const Point &p0,const Point &p1){
    return p0.x*p1.x+p0.y*p1.y;
}
//向量长度
inline double Length(Point &P){
    return sqrt(Dot(P,P));
}
//向量夹角
double Angle(Point A,Point B){
    return acos(Dot(A,B)/Length(A)/Length(B));
}
//面积
inline double Area2(const Point &A,const Point &B,const Point &C){
    return Mul(A,B,C);
}
//向量旋转
Point Rotate(Point A,double rad){//旋转角度rad
    return Point(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
//向量法线
Point Normal(Point A){
    double L=Length(A);
    return Point(-A.y/L,A.x/L);
}

///点和直线
//直线交点
Point GetLineInter(Point P,Point v,Point Q,Point w){
    Point u=P-Q;//P:直线l1上的某点,v:直线l1上的单位向量
    double t=(w^u)/(v^w);
    return P+v*t;
}
//点到直线的距离
double DistanceToLine(Point P,Point A,Point B){
    Point AP=P-A;Point AB=B-A;//A.B:直线上的两点
    return fabs(AP^AB)/Length(AB);
}
//点到线段的距离
double DistanceToSegment(Point P,Point A,Point B){
    Point AB=B-A;Point AP=P-A;Point BP=P-B;
    if(A==B) return Length(AP);
    if(sign(Dot(AB,AP))==-1) return Length(AP);
    else if(sign(Dot(AB,BP))==1) return Length(BP);
    else return fabs(AB^AP)/Length(AB);
}
// 点在直线上的投影
Point GetLineProjection(Point P,Point A,Point B){
    Point 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=(a2-a1)^(b1-a1),c2=(a2-a1)^(b2-a1);//a1.a2:线段的两个端点
    double c3=(b2-b1)^(a1-b2),c4=(b2-b1)^(a2-b2);
    return sign(c1)*sign(c2)<0&&sign(c3)*sign(c4) < 0;
}
// 直线情况判定(一次跨立实验)
inline int SegmentProperIntersection(const Point &a1,const Point &a2,const Point &b1,const Point &b2){
    double c1=(a2-a1)^(b1-a1),c2=(a2-a1)^(b2-a1);//a1.a2:直线上的点
    if(sign(c1)==0&&sign(c2)==0) return 2;//重叠
    if(sign(c1-c2)==0) return 0;//平行
    return 1;//相交
}
// 点是否在线段上
bool OnSegment(Point P,Point a1,Point a2){
    return sign((a1-P)^(a2-P))==0&&sign(Dot(a1-P,a2-P))==-1;
}
// 多边形的有向面积
double PolygonArea(Point *P,int n){
    double area=0;
    for(int i=1;i<n-1;i++)
        area+=(P[i]-P[0])^(P[i+1]-P[0]);
    return area/2;
}
/// 点在多边形内的判定
int IsPointInPolygon(Point p,Point *poly,int n){
    int wn=0;//n:多边形边数,poly:多边形顶点
    for(int i=0;i<n;i++){
        if(OnSegment(p,poly[i],poly[(i + 1)% n])) return -1;
        int k=sign((poly[(i + 1)%n]-poly[i])^(p-poly[i]));
        int d1=sign(poly[i].y-p.y);
        int d2=sign(poly[(i + 1)%n].y-p.y);
        if(k<0&&d1<=0&&d2>0) wn++;
        if(k>0&&d2<=0&&d1>0) wn--;
    }
    // 1:in     0:out
    if(wn!=0) return 1;
    return 0;
}
/// 求凸包(P:所有点)(ch:凸包上的点)
int ConvexHull(Point* P,int n,Point* ch){
    sort(P,P+n);
    int m=0;
    for(int i=0;i<n;i++){
        while(1<m&&sign((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;0<=i;i--){
        while(k<m&&sign((ch[m-1]-ch[m - 2])^(P[i]-ch[m-2]))<=0) m--;
        ch[m++]=P[i];
    }
    if(1<n) m--;
    return m;
}

int main(){
    return 0;
}
//三角形外接圆圆心以及半径
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;

typedef long long ll;
const int Max_n=1e5+10;
const double eps=1e-10;
const double pi=acos(-1.0);

inline int sign(const double &x){//判断一个数(double)的正负
    if(x>eps) return 1;
    if(x<-eps) return -1;
    return 0;
}

struct Point{//定义一个向量的类型(点可以看做另一个端点(0,0)的向量)
    double x,y;
    //Point(){}
    Point(double _x=0,double _y=0):x(_x),y(_y){}//构造函数
    Point operator +(const Point &P) const{//向量减
        return Point(x+P.x,y+P.y);//使用构造函数
    }
    Point operator -(const Point &P) const {//向量减
        return Point(x-P.x,y-P.y);
    }
    double operator ^(const Point &P) const{//向量叉积
        return x*P.y-y*P.x;
    }
    Point operator *(const double &val) const{//向量乘实数
        return Point(x*val,y*val);
    }
    Point operator /(const double &val) const{//向量除以实数
        return Point(x/val,y/val);
    }
    bool operator < (const Point &P) const {//重载小于运算符(排序使用)
        return x<P.x||(x==P.x&&y<P.y);
    }
    bool operator == (const Point &P) const {
        return sign(x-P.x)==0&&sign(y-P.y)==0;
    }
}p1,p2,p3;

//计算两点间距离
inline double Dis(const Point &p0,const Point &pi){//|p0pi|^2
    return (p0.x-pi.x)*(p0.x-pi.x)+(p0.y-pi.y)*(p0.y-pi.y);
}

inline double S(const Point &p1,const Point &p2,const Point &p3){
    return (p1.x-p3.x)*(p2.y-p3.y)-(p1.y-p3.y)*(p2.x-p3.x);
}

//计算两个向量的点积
inline double Dot(const Point &p0,const Point &p1){
    return p0.x*p1.x+p0.y*p1.y;
}
//向量长度
inline double Length2(Point &P){
    return Dot(P,P);
}

int main(){
    while(~scanf("%lf%lf%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y,&p3.x,&p3.y)){
        double a=Dis(p1,p2);
        double b=Dis(p2,p3);
        double c=Dis(p3,p1);
        double r=sqrt(a*b*c)/sqrt((a+b+c)*(a+b+c)-2*(a*a+b*b+c*c));//外接圆半径
        //printf("%.3lf\n",r);
        double s=S(p1,p2,p3);
        double s1=S(Point(Length2(p1),p1.y),Point(Length2(p2),p2.y),Point(Length2(p3),p3.y));
        double s2=S(Point(p1.x,Length2(p1)),Point(p2.x,Length2(p2)),Point(p3.x,Length2(p3)));
        double x0=-s1/(2*s);
        double y0=-s2/(2*s);//外接圆圆心(x0,y0);
        printf("(x %c %.3f)^2 + (y %c %.3f)^2 = %.3f^2\n",sign(x0)>0?'+':'-',fabs(x0),sign(y0)>0?'+':'-',fabs(y0),r);
        printf("x^2 + y^2 %c %.3fx %c %.3fy %c %.3f = 0\n\n",sign(2*x0)>0?'+':'-',fabs(2*x0),
               sign(2*y0)>0?'+':'-',fabs(2*y0),sign(x0*x0+y0*y0-r*r)>0?'+':'-',fabs(x0*x0+y0*y0-r*r));
    }
    return 0;
}
发布了166 篇原创文章 · 获赞 68 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_42217376/article/details/98964994