計算幾何常用的函式/方法
(一)求多邊形的面積(用叉積計算)
程式碼如下:
//叉積,可以用來判斷方向和求面積
double cross(Point a,Point b,Point c){
return (c.x-a.x)*(b.y-a.y) - (b.x-a.x)*(c.y-a.y);
}
//求多邊形的面積
double S(Point p[],int n){
double ans = 0;
p[n] = p[0];
for(int i=1;i<n;i++)
ans += cross(p[0],p[i],p[i+1]);
if(ans < 0) ans = -ans;
return ans / 2.0;
}
(二)求多邊形的重心
程式碼如下:
//求多邊形的重心
Point grabity(Point p[],int n){
Point G;
double sum_area=0;
for(int i=2;i<n;i++){
double area = cross(p[0],p[i-1],p[i]);
sum_area+=area;
G.x+=(p[0].x+p[i-1].x+p[i].x)*area;
G.y+=(p[0].y+p[i-1].y+p[i].y)*area;
}
G.x=G.x/3/sum_area,G.y=G.y/3/sum_area;
return G;
}
(三)andrew演算法求凸包
程式碼如下:
/**
求二維凸包Andrew演算法,將所有的點按x小到大(x相等,y小到大)排序
刪去重複的點,得到一個序列p1,p2...,然後把p1,p2放入凸包中,從p3
開始當新點再前進方向左邊時(可以用叉積判斷方向)繼續,否則,依次
刪除最近加入凸包的點,直到新點再左邊。
**/
int ConvexHull(Point *p,int n,Point *stack){
sort(p,p+n);
n=unique(p,p+n)-p;
int m=0;
for(int i=0;i<n;i++){//如果不希望凸包的邊上有輸入的點則把兩個等號去掉
while(m>1&&cross(stack[m-2],p[i],stack[m-1])<=0) m--;
stack[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;i--){
while(m>k&&cross(stack[m-2],p[i],stack[m-1])<=0)m--;
stack[m++]=p[i];
}
if(n>1) m--;
return m;
}
(四)比較函式提高精度:
//判斷符號,提高精度
int dcmp(double x){
if(fabs(x)<eps) return 0;
else return x < 0 ? -1 : 1;
}
(五)向量/以及常見運算過載
struct Point{
double x,y;
Point():x(0),y(0){}
Point(double _x,double _y):x(_x),y(_y){}
bool operator <(const struct Point &tmp) const{
if(x==tmp.x) return y<tmp.y;
return x<tmp.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);
}
bool operator == (Vector A,Vector B){
return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0;
}
double Dot(Vector A, Vector B){//向量相乘
return A.x*B.x + A.y*B.y; //a*b*cos(a,b)
}
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;
}
/**
向量(x,y) 繞起點逆時針旋轉a度。
x' = x*cosa - y*sina
y' = x*sina + y*cosa
**/
Vector Rotate(Vector A,double a){
return Vector (A.x*cos(a)-A.y*cos(a),A.x*sin(a)+A.y*cos(a));
}
double trans(double ang){
return ang/180*acos(-1.0);
}
(六)旋轉卡殼求凸包的直徑,平面最遠的點對
程式碼如下:
//旋轉卡殼求凸包的直徑,平面距離最遠的點對的距離
double rotatint_calipers(Point *p,int n){
int k=1;
int ans = 0;
p[n]=p[0];
for(int i=0;i<n;i++){
while(fabs(Cross(p[i+1],p[k],p[i]))<fabs(Cross(p[i+1],p[k+1],p[i])))
k=(k+1)%n;
ans = max(ans,max(dis(p[i],p[k]),dis(p[i+1],p[k])));
}
return ans;
}
(七)旋轉卡殼求凸包的寬度,即找一組距離最近的平行線似的凸包的點在兩根線的內側
程式碼如下:
double rotating_calipers(Point *p,int n){
int k = 1;
double ans = 0x7FFFFFFF;
p[n] = p[0];
for(int i=0;i<n;i++){
while(fabs(cross(p[i],p[i+1],p[k])) < fabs(cross(p[i],p[i+1],p[k+1])))
k = (k+1) % n;
double tmp = fabs(cross(p[i],p[i+1],p[k]));
double d = dist(p[i],p[i+1]);
ans = min(ans,tmp/d);
}
return ans;
}
(八)求線段的中垂線
//求線段的中垂線
inline Line getMidLine(const Point &a, const Point &b) {
Point mid = (a + b);
mid.x/=2.0;
mid.y/=2.0;
Point tp = b-a;
return Line(mid, mid+Point(-tp.y, tp.x));
}
(九)直線相關
struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;
e = _e;
}
bool operator ==(Line v)
{
return (s == v.s)&&(e == v.e);
}
void input()
{
s.input();
e.input();
}
//兩線段相交判斷
//2 規範相交
//1 非規範相交
//0 不相交
int segcrossseg(Line v)
{
int d1 = sgn((e-s)^(v.s-s));
int d2 = sgn((e-s)^(v.e-s));
int d3 = sgn((v.e-v.s)^(s-v.s));
int d4 = sgn((v.e-v.s)^(e-v.s));
if( (d1^d2)==-2 && (d3^d4)==-2 )return 2;
return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
(d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
(d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
(d4==0 && sgn((e-v.s)*(e-v.e))<=0);
}
//直線和線段相交判斷
//-*this line -v seg
//2 規範相交
//1 非規範相交
//0 不相交
int linecrossseg(Line v)
{
int d1 = sgn((e-s)^(v.s-s));
int d2 = sgn((e-s)^(v.e-s));
if((d1^d2)==-2) return 2;
return (d1==0||d2==0);
}
};
相關文章
- 計算幾何 —— 二維幾何基礎 —— 距離度量方法
- 【IDL】幾何圖形數學運算函式函式
- 計算幾何
- 計算幾何:模板
- 計算幾何模板
- python 的幾個常用的函式Python函式
- webgl內建函式--幾何函式與矩陣函式Web函式矩陣
- Something about 計算幾何
- [筆記] 計算幾何筆記
- mysql注入方法邏輯運算及常用函式MySql函式
- matchTemplate函式各個方法的計算公式函式公式
- NumPy常用的位運算函式函式
- 微分幾何學習(一)(向量函式)函式
- CityEngine函式庫1-幾何建立函式
- SGU 124 Broken line(計算幾何)
- 計算幾何——平面最近點對
- POJ - 1556 【計算幾何 + 最短路】
- 【學習筆記】計算幾何筆記
- 邊緣計算、霧計算、雲端計算區別幾何?
- BNUOJ 12887 isumi(計算幾何+最大流)
- SGU 120 SGU 228 Archipelago(計算幾何)Go
- Kotlin中的幾個常用函式let with run also applyKotlin函式APP
- oracle 系統自帶幾個常用函式Oracle函式
- Unity&Shader常用函式的使用方法Unity函式
- python中關於時間和日期函式的常用計算總結Python函式
- 函式計算安裝依賴庫方法小結函式
- 計算檔案Checksum的幾種方法
- AppDelegate中幾個常用回撥函式的呼叫時機APP函式
- 瞭解React Hooks及其常用的幾個鉤子函式ReactHook函式
- 計算幾何(一):凸包問題(Convex Hull)
- POJ 1113 Wall(思維 計算幾何 數學)
- Mysql 常用函式(1)- 常用函式彙總MySql函式
- 計算 CRC32 的逆函式函式
- Js常用的函式JS函式
- 常用的Css函式CSS函式
- python的常用函式Python函式
- 函式間隔(functional margin)和幾何間隔(geometric margin)函式Function
- 函式計算——應用初探函式
- 常用函式函式