首页 > 其他分享 >计算几何模板

计算几何模板

时间:2023-08-22 16:56:27浏览次数:36  
标签:return pt ans vec 计算 几何 inline line 模板

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8,pi=acos(-1.0);
const int N=100005;
inline int dcmp(double x){return (x<-eps)?-1:(x>eps)?1:0;}//判断正负
inline double dabs(double x){return x*dcmp(x);}//绝对值 
/*向量(点)*/
struct vec{double x,y;vec(double _x=0,double _y=0){x=_x;y=_y;}};
inline bool cmp_vec(vec a,vec b){return (a.x!=b.x)?a.x<b.x:a.y<b.y;}
inline double len(vec a){return sqrt(a.x*a.x+a.y*a.y);}//模长 
inline double ang(vec a){return atan2(a.y,a.x);}//角度 
inline vec operator +(const vec &a,const vec &b){return vec(a.x+b.x,a.y+b.y);}
inline vec operator -(const vec &a,const vec &b){return vec(a.x-b.x,a.y-b.y);}
inline vec operator *(const vec &a,const double &b){return vec(a.x*b,a.y*b);}
inline vec operator /(const vec &a,const double &b){return vec(a.x/b,a.y/b);}
inline double operator *(const vec &a,const vec &b){return a.x*b.x+a.y*b.y;}//点积 
inline double operator ^(const vec &a,const vec &b){return a.x*b.y-a.y*b.x;}//叉积
inline vec rot(vec a,double the){return vec(a.x*cos(the)-a.y*sin(the),a.x*sin(the)+a.y*cos(the));}//旋转 
inline vec rot90(vec a){return vec(a.y,-a.x);}//特殊角旋转
inline vec rotpt(vec a,vec b,double the){return b+rot(a-b,the);}//a绕b旋转
/*线*/ 
struct line{vec s,t;line(vec _s=vec(0,0),vec _t=vec(0,0)){s=_s;t=_t;}};//线 
inline double maxx(line l){return max(l.s.x,l.t.x);}//大x
inline double maxy(line l){return max(l.s.y,l.t.y);}//大y 
inline double minx(line l){return min(l.s.x,l.t.x);}//小x
inline double miny(line l){return min(l.s.y,l.t.y);}//小y
inline double ang(line l){return ang(l.t-l.s);}//角度 
inline bool operator <(line &a,line &b){double a1=ang(a.t-a.s),a2=ang(b.t-b.s);return (dcmp(a2-a1))?a2>a1:dcmp((a.t-a.s)^(b.t-b.s))<0;} 
inline bool operator ==(vec &a,vec &b){return (!dcmp(a.x-b.x)&&!dcmp(a.y-b.y));}//点是否相等 
inline double dis(vec a,vec b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}//点距离
inline bool pd_pl(vec a,line b){return !dcmp((a-b.s)^(b.t-b.s));}//点是否在直线上
inline bool pd_px(vec a,line b){return pd_pl(a,b)&&(dcmp((a-b.s)*(a-b.t))<=0);}//点是否在线段上
inline vec footpt(vec a,line b){vec x=a-b.s,y=a-b.t,z=b.t-b.s;double s1=x*z,s2=-1.0*(y*z);return b.s+z*(s1/(s1+s2));}//求垂足(分别求as,at关于st的投影)
inline vec mirror(vec a,line b){return a+(footpt(a,b)-a)*2.0;}//a关于b的对称点
inline double dis_pl(vec a,line b){return dabs((a-b.s)^(a-b.t))/len(b.t-b.s);}//求a到直线b的距离(面积除以底边长)
inline double dis_px(vec a,line b){return (dcmp((a-b.s)*(b.t-b.s))<0)?len(a-b.s):(dcmp((a-b.t)*(b.t-b.s))>0)?len(a-b.t):dis_pl(a,b);}//求a到线段b的距离
inline vec pt_px(vec a,line b){return (dcmp((a-b.s)*(b.t-b.s))<0)?b.s:(dcmp((a-b.t)*(b.t-b.s))>0)?b.t:footpt(a,b);}//在线段b上与a最近的点
inline vec cross(line a,line b){vec x=a.t-a.s,y=b.t-b.s,z=a.s-b.s;return a.s+x*((y^z)/(x^y));}//求a与b的交点
inline bool pd_cross_lx(line a,line b){return (!dcmp((a.t-a.s)^(b.t-b.s)))?0:pd_px(cross(a,b),a);}//线段a与直线b是否相交
inline bool pd_cross_xx(line a,line b){return pd_cross_lx(a,b)&&pd_cross_lx(b,a);}//判断线段a是否与线段b相交
inline bool pd_cross_xx_(line a,line b)//判断两线段是否相交 (另一种方法,是否跨立) 
{
	if(maxx(a)<minx(b)||maxy(a)<miny(b)) return false;
	if(maxx(b)<minx(a)||maxy(b)<miny(a)) return false;
	double s1=(a.t-a.s)^(b.s-a.s),s2=(a.t-a.s)^(b.t-a.s);
	double s3=(b.t-b.s)^(a.s-b.s),s4=(b.t-b.s)^(a.t-b.s);
	return dcmp(s1)*dcmp(s2)<=0&&dcmp(s3)*dcmp(s4)<=0;//a的端点在b的两侧且b的端点在a的两侧 
}
inline double s_t(vec a,vec b,vec c){return dabs((b-a)*(c-a))/2;}//已知三点求三角形面积 
/*多边形*/
struct pol
{
	vector<vec> pt;
	inline vec& operator [](int x){return pt[x];}
	inline int ne(int x){return (x<pt.size()-1)?x+1:0;}
	inline void insert(vec p){pt.push_back(p);}
	inline void clear(){pt.clear();}
	inline int include(vec p)//点在多边形外:0,在多边形内:1,在多边形边上:2 
	{
		int cnt=0;
		for(int i=0;i<pt.size();i++)//射线法判断,射线方向为x轴正方向 
		{
			vec s=pt[i],t=pt[ne(i)];line l=line(s,t);
			if(pd_px(p,l)) return 2;
			if(dcmp(p.y-miny(l))>=0&&dcmp(maxy(l)-p.y)>0)
			if(dcmp(s.x+((p.y-s.y)/(t.y-s.y)*(t.x-s.x))-p.x)>0) cnt++;
		}
		return cnt&1;//偶数个交点则在多边形外,奇数个交点则在多边形内 
	}
	inline double s_p()//多边形面积 
	{
		double ans=0;
		for(int i=1;i<pt.size()-1;i++) ans+=(pt[i]-pt[0])^(pt[ne(i)]-pt[0]);
		return dabs(ans)/2;
	}
	inline double c_p()//多边形周长 
	{
		double ans=0;
		for(int i=0;i<pt.size();i++) ans+=dis(pt[i],pt[ne(i)]);
		return ans;
	}
	inline bool pd_l(vec x,vec l,vec r){return dcmp((l-x)^(r-x))<=0;}//xl是否在xr的左侧
	inline int include_(vec p)//二分法判断点是否在多边形内
	{
		int n=pt.size();
		if(!pd_l(pt[0],p,pt[1])) return 0;
		if(!pd_l(pt[0],pt[n-1],p)) return 0; 
		if(pd_px(p,line(pt[0],pt[1]))) return 2;
		if(pd_px(p,line(pt[0],pt[n-1]))) return 2;
		int l=1,r=n-2,ans=1,mid;
		while(l<=r)//二分找到最接近线(pt[0],p)的(pt[0],pt[ans]) 
		{
			mid=l+r>>1;
			if(!pd_l(pt[0],pt[mid],p)) l=mid+1,ans=mid;
			else r=mid-1;
		}
		if(!pd_l(pt[ans],p,pt[ne(ans)])) return 0;
		if(pd_px(p,line(pt[ans],pt[ne(ans)]))) return 2;
		return 1;
	} 
};
/*凸包*/
inline void andrew(pol &p)
{
	vector<vec>q(p.pt.size()<<1);int top=0,n=p.pt.size();
	sort(p.pt.begin(),p.pt.end(),cmp_vec),q[top]=p[0];
	for(int i=1;i<n;i++)
	{
		while(top&&dcmp((q[top-1]-q[top])^(q[top-1]-p[i]))<=0) top--;
		q[++top]=p[i];
	}
	int tot=top;
	for(int i=n-2;i>=0;i--)
	{
		while(top>tot&&dcmp((q[top-1]-q[top])^(q[top-1]-p[i]))<=0) top--;
		q[++top]=p[i];
	}
	if(n>1) top--;
	p.clear();
	for(int i=0;i<=top;i++) p.insert(q[i]);
}
/*旋转卡壳*/
inline double diam(pol p)
{
	int n=p.pt.size();double ans=0;
	for(int i=0,j=1;i<n;i++)
	{
		for(;;j=p.ne(j)) if(dcmp(s_t(p[j],p[i],p[p.ne(i)])-s_t(p[p.ne(j)],p[i],p[p.ne(i)]))>=0) break;
		ans=max(ans,max(dis(p[j],p[i]),dis(p[j],p[p.ne(i)])));
	}
	return ans;
}```

标签:return,pt,ans,vec,计算,几何,inline,line,模板
From: https://www.cnblogs.com/One-JuRuo/p/17648995.html

相关文章

  • C语言 计算一个数的阶乘两种方法
    //ConsoleApplication15.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。//#include<iostream>#include<stdio.h>usingnamespacestd;longfact(intn);//使用循环方法longrfact(intn);//使用递归方法intmain(void){  intnum;  printf("Thisprog......
  • 基于JAVA的二手手机回收系统-计算机毕业设计源码+LW文档
    摘要随着信息技术的发展,基于web模式的购物系统逐渐普及,网上购物是一种新型的商务模式,其工作流程和经营模式受到了欢迎。电子商务可以适应现代化快节奏的生活方式,满足各类人群足不出户的在线购物,利用商城使得买卖双方完成线上交易,提高了购买效率。但随着网购二手手机数量的增多,存......
  • 在线外语学习平台-计算机毕业设计源码+LW文档
    提要信息化的迅速发展,对人们的衣食住行产生了很大影响。越来越多的人习惯并依赖于通过信息技术和智能化的形式来处理日常各类事物。为了满足学生用户日常学习的需要,以及适应现代化课程教学管理的需求,决定开发在线外语学习平台。帮助学生在线学习,提高效率。在线外语学习平台的开发......
  • 基于JAVA+MySQL技术智能服装推荐系统的设计与实现-计算机毕业设计源码+LW文档
    1.开题依据1.1研究的目的意义在过去到现在,消费方式从物物交换到以通俗认知中的“货币”购买物品,再到如今的网上支付交易,实物物流运输到达我们的手上。购物方式从实体店的消费模式,转到了网上店铺的交易。相信很多人在现实生活中都有过实体店购物的消费的体验,在实体店消费需要安排......
  • 学生公寓管理系统设计-计算机毕业设计源码+LW文档
    1.1研究背景教育是国家发展的基石,随着目前经济快速的发展,国家也更加重视教育事业,大力发展义务教育并提升高等教育。随着高校扩招的推进,高校宿舍的数量越来越多,宿舍信息和学生管理也变得越来越困难。在传统的宿舍管理中,高校往往通过大量的人力和物力进行管理,通过手工记录宿舍信息,统......
  • 模板相关的摘录总结
    函数模板的实例化隐式实例化:让编译器自己根据实参的类型推导模板参数的类型template<classT>TAdd(constT&a,constT&b){ returna+b;}intmain(){ inta=1,b=2; cout<<Add(a,b)<<endl;}显示实例化:在函数名后的<>中指定模板参数的实际类型tem......
  • ubuntu 修改计算机名字
     vimetc/hostname   vim/etc/hosts   retboot ......
  • TemplateMethodPattern-模板方法模式
    在C#中,模板方法模式(TemplateMethodPattern)是一种行为型设计模式,它定义了一个算法的骨架,将某些步骤延迟到子类中实现。模板方法模式通过将公共的算法步骤抽象到基类中,并且通过在基类中定义一个模板方法来调用这些步骤,从而实现代码的复用和灵活性。模板方法模式有以下几个关键角......
  • 窗口函数大揭秘!轻松计算数据累计占比,玩转数据分析的绝佳利器
    上一篇文章《如何用窗口函数实现排名计算》中小编为大家介绍了窗口函数在排名计算场景中的应用,但实际上窗口函数除了可以进行单行计算,还可以在每行上打开一个指定大小的计算窗口,这个计算窗口可以由SQL中的语句具体指定,大到整个分区作用域,小到当前行指定的某个偏移行(比如当前行的......
  • C++遍历TypeList(可变模板参数)的简单办法
        这里例举了两种方案,一种是基于C++17的constexpr,实现起来更精简。另外一种使用传统的方式,C++11就可以用了。    另外C++11的方案也是一种计算不定参数模板参数个数的方法。#include<iostream>#include<string>//inC++17#if((defined(_MSVC_LANG)......