xyz的计算圆与多边形相交面积模板

#include<bits/stdc++.h>
 
using namespace std;
 
const double eps = 1e-8;
const double PI = acos(-1.0);
 
int dcmp(double x){//判断误差在eps范围内 
    if( x > eps ) return 1;
    return x < -eps ? -1 : 0;
}
 
struct Point{
    double x,y;
    Point(){
        x = y = 0;
    }
    Point(double a,double b){//给点赋值 
        x = a;y = b;
    }
    inline void input(){
        scanf("%lf%lf",&x,&y);//输入点的座标 
    }
    inline Point operator-(const Point &b)const{//求点a、b构成的向量 
        return Point(x - b.x,y - b.y);
    }
    inline Point operator+(const Point &b)const{
        return Point(x + b.x,y + b.y);
    }
    inline Point operator*(const double &b)const{
        return Point(x * b,y * b);
    }
    inline double dot(const Point &b)const{//点乘 
        return x * b.x + y * b.y;
    }
    inline double cross(const Point &b,const Point &c)const{//多边形一边上的两点与圆心形成的向量叉乘 
        return (b.x - x) * (c.y - y) - (c.x - x) * (b.y - y);
    }
    inline double Dis(const Point &b)const{//求圆心与点之间的距离 
        return sqrt((*this-b).dot(*this-b));
    }
    inline bool InLine(const Point &b,const Point &c)const{ //三点共线 
        return !dcmp(cross(b,c));
    }
    inline bool OnSeg(const Point &b,const Point &c)const{ //点在线段上,包括端点 
        return InLine(b,c) && (*this - c).dot(*this - b) < eps;
    }
};
 
inline double min(double a,double b){
    return a < b ? a : b;
}
inline double max(double a,double b){
    return a > b ? a : b;
}
inline double Sqr(double x){
    return x * x;
}
inline double Sqr(const Point &p){
    return p.dot(p);
}
 
Point LineCross(const Point &a,const Point &b,const Point &c,const Point &d){
    double u = a.cross(b,c) , v = b.cross(a,d);
    return Point((c.x * v + d.x * u) / (u + v) , (c.y * v + d.y * u) / (u + v));
} 
 
double LineCrossCircle(const Point &a,const Point &b,const Point &r,
    double R,Point &p1,Point & p2){
    Point fp = LineCross(r , Point(r.x+a.y-b.y , r.y+b.x-a.x) , a , b);
    double rtol = r.Dis(fp);
    double rtos = fp.OnSeg(a , b) ? rtol : min(r.Dis(a) , r.Dis(b));
    double atob = a.Dis(b);
    double fptoe = sqrt(R * R - rtol * rtol) / atob;
    if( rtos > R - eps ) return rtos;
    p1 = fp + (a - b) * fptoe;
    p2 = fp + (b - a) * fptoe;
    return rtos;
}
 
double SectorArea(const Point &r,const Point &a,const Point &b,double R){ //不大于180度扇形面积,r->a->b逆时针 
    double A2 = Sqr(r - a) , B2 = Sqr(r - b) , C2 = Sqr(a - b);
    return R * R * acos( (A2 + B2 - C2) * 0.5 / sqrt(A2) / sqrt(B2)) * 0.5;
}
 
double TACIA(const Point &r,const Point &a,const Point &b,double R){
    double adis = r.Dis(a) , bdis = r.Dis(b);
    if( adis < R + eps && bdis < R + eps )//两点,也就是该边在圆内 
        return r.cross(a , b) * 0.5;
    Point ta , tb;
    if( r.InLine(a,b) ) return 0.0;//三点共线,则 
    double rtos = LineCrossCircle(a, b, r, R, ta, tb);
    if( rtos > R - eps ) 
        return SectorArea(r, a, b, R);
    if( adis < R + eps )
        return r.cross(a, tb) * 0.5 + SectorArea(r, tb, b, R);
    if( bdis < R + eps )
        return r.cross(ta, b) * 0.5 + SectorArea(r, a, ta, R);
    return r.cross(ta, tb) * 0.5 + SectorArea(r, tb, b, R) + SectorArea(r, a, ta, R);
}
 
const int MAXN  = 505;
Point p[MAXN];
 
double SPICA(int n,Point r,double R){
    int i;
    double ret = 0 , if_clock_t;
    for( i = 0 ; i < n ; ++i ){
        if_clock_t = dcmp(r.cross(p[i], p[(i + 1) % n]));//如果if_clock_t<0说明两个向量叉乘小于0,两个向量所成夹角为钝角,
        //这两个向量与p[i]、p[i+1]的边形成的三角形在圆和多边形外。 
        if( if_clock_t < 0 )
            ret -= TACIA(r, p[(i + 1) % n], p[i], R);
        else ret += TACIA(r, p[i], p[(i + 1) % n], R);
    }
    return fabs(ret);
}
 
int main(){
    int n;
    double x0,y0,ang,v0,g,t,r,vx,vy;
    while(scanf("%lf %lf %lf %lf %lf %lf %lf",&x0,&y0,&v0,&ang,&t,&g,&r)!=EOF)
    {
     if(x0==0&&y0==0&&v0==0&ang==0&&t==0&&g==0&&r==0)
     break;
    scanf("%d",&n);//多边形n个顶点 
    for(int i = 0 ; i < n ; ++i ) //顶点坐标 
        p[i].input();
        vx = v0*cos(ang/180*PI);
        vy = v0*sin(ang/180*PI);
    Point circle;
    //circle.input(); //圆心坐标 
    circle.x = x0+vx*t;
    circle.y = y0+vy*t-g*t*t/2;
    printf("%.2f\n",SPICA(n,circle,r));
   }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要计算python中经纬度对应的直线与的交点,需要使用数学库如numpy和Shapely。下面是一个简单的步骤: 1. 首先,导入所需的库,包括numpy和Shapely: ```python import numpy as np from shapely.geometry import Point, LineString ``` 2. 定义经纬度点的坐标和心的经纬度坐标: ```python lat1 = 40.7128 # 点1的纬度 lon1 = -74.0060 # 点1的经度 lat2 = 41.8781 # 点2的纬度 lon2 = -87.6298 # 点2的经度 circle_center_lat = 43.6532 # 心的纬度 circle_center_lon = -79.3832 # 心的经度 circle_radius = 100 # 的半径(单位:米) ``` 3. 根据经纬度点创建直线和对象: ```python point1 = Point(lon1, lat1) point2 = Point(lon2, lat2) line = LineString([point1, point2]) circle = Point(circle_center_lon, circle_center_lat).buffer(circle_radius / 111000) ``` 4. 计算直线与的交点: ```python intersection_points = line.intersection(circle) ``` 5. 获取交点的经纬度坐标: ```python intersection_coordinates = [] if intersection_points.geom_type == 'Point': intersection_coordinates.append((intersection_points.x, intersection_points.y)) elif intersection_points.geom_type == 'MultiPoint': for point in intersection_points: intersection_coordinates.append((point.x, point.y)) ``` 这样就可以通过给定的经纬度点、心和半径计算出直线与的交点的经纬度坐标了。请注意,以上代码只是一个示例,实际使用中需要根据具体情况进行调整。 ### 回答2: 在Python中,我们可以使用数学库或第三方库来计算直线与的交点。下面是一种使用sympy库进行计算的方法: 1. 首先,我们需要引入sympy库,并创建直线和的符号变量。 ``` import sympy as sp x, y = sp.symbols('x y') ``` 2. 接下来,我们需要定义直线和的方程。 ``` line_eq = sp.Eq(y, mx + c) # 直线方程,其中m为斜率,c为截距 circle_eq = sp.Eq((x - a)**2 + (y - b)**2, r**2) # 的方程,其中(a, b)为心坐标,r为半径 ``` 3. 然后,我们需要解这两个方程得到交点。 ``` intersection_points = sp.solve((line_eq, circle_eq), (x, y)) ``` 4. 最后,我们可以通过循环遍历得到的交点,并打印出它们的坐标。 ``` for point in intersection_points: x_val = sp.re(point[0]) # 提取实部,获取交点的x坐标 y_val = sp.re(point[1]) # 提取实部,获取交点的y坐标 print(f"交点的坐标为:({x_val}, {y_val})") ``` 请注意,以上代码只是给出了一种实现方式,具体的方程和计算方式可能根据问题的具体要求略有不同。 ### 回答3: 要通过经纬度计算直线与的交点,首先需要确定心的经纬度坐标和半径,以及直线上两个点的经纬度坐标。 1. 将经纬度坐标转换成大地坐标系中的三维直角坐标系(XYZ坐标系)。可以使用WGS84椭球模型将经纬度转化为XYZ坐标,公式如下: X = cos(lat) * cos(lon) Y = cos(lat) * sin(lon) Z = sin(lat) 其中,lat为纬度,lon为经度。 2. 计算直线的方程。假设直线上的两个点分别为A和B,它们的XYZ坐标分别为A(Xa, Ya, Za)和B(Xb, Yb, Zb)。根据两点式得到直线方程为: (x - Xa)/(Xb - Xa) = (y - Ya)/(Yb - Ya) = (z - Za)/(Zb - Za) 3. 计算直线与的交点。 a. 对于直线方程,将z用X和Y替换,得到: (x - Xa)/(Xb - Xa) = (y - Ya)/(Yb - Ya) = (sin(lat) - Za)/(Zb - Za) b. 将心的XYZ坐标代入,得到: (x - Xa)/(Xb - Xa) = (y - Ya)/(Yb - Ya) = (sin(latC) - Za)/(Zb - Za) 其中,latC为心的纬度。 c. 将直线和的方程联立,解方程组,得到交点坐标(x, y, z)。 4. 将交点的XYZ坐标转换回经纬度坐标。可以使用逆转换公式将XYZ坐标转化为经纬度。具体步骤是: a. 计算球面上的高度h和长度d,公式为: h = sqrt(x^2 + y^2 + z^2) - R d = sqrt(x^2 + y^2) b. 计算纬度和经度的值,公式为: lat = atan2(z / h, d / h) # 弧度换算成角度 lon = atan2(y, x) # 弧度换算成角度 通过以上步骤,可以计算出直线与的交点的经纬度坐标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值