前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >两圆相交到两球相交

两圆相交到两球相交

作者头像
Enterprise_
发布2019-02-20 10:41:41
7470
发布2019-02-20 10:41:41
举报
文章被收录于专栏:小L的魔法馆小L的魔法馆

首先,定义一些东西

代码语言:javascript
复制
const double PI = acos(-1.0);
typedef struct point {
    double x,y;
    point() {
    }
    point(double a, double b) {
        x = a;
        y = b;
    }
    point operator -(const point &b)const {     //返回减去后的新点
        return point(x - b.x, y - b.y);
    }
    point operator +(const point &b)const {     //返回加上后的新点
        return point(x + b.x, y + b.y);
    }
    point operator *(const double &k)const {    //返回相乘后的新点
        return point(x * k, y * k);
    }
    point operator /(const double &k)const {    //返回相除后的新点
        return point(x / k, y / k);
    }
    double operator ^(const point &b)const {    //叉乘
        return x*b.y - y*b.x;
    }
    double operator *(const point &b)const {    //点乘
        return x*b.x + y*b.y;
    }
}point;
typedef struct circle {//圆
    double r;
    point centre;
}circle;

double dist(point p1, point p2) {       //返回平面上两点距离
    return sqrt((p1 - p2)*(p1 - p2));
}
这里写图片描述
这里写图片描述
  • 两圆相交 两圆关系,可以根据圆心距离和半径的关系来判断,现在只考虑相交的情况,即圆心距LLL在两圆半径之和|r1+r2||r1+r2||r_1+r_2|及两圆半径之差|r1−r2||r1−r2||r_1-r_2|之间。 如上图所示,已知r1,r2,Lr1,r2,Lr_1,r_2,L那就可以得到很多东西。 根据勾股定理,可以得到 r21−h21=l21r12−h12=l12r_1^2-h_1^2=l_1^2 r22−h21=l22r22−h12=l22r_2^2-h_1^2=l_2^2 L=l1+l2L=l1+l2L=l_1+l_2 联立推出 h1=r21−(L2+r21−r222L)2−−−−−−−−−−−−−√h1=r12−(L2+r12−r222L)2h_1=\sqrt{r_1^2-(\frac{L^2+r_1^2-r_2^2}{2L})^2} h1=r22−(L2+r22−r212L)2−−−−−−−−−−−−−√h1=r22−(L2+r22−r122L)2h_1=\sqrt{r_2^2-(\frac{L^2+r_2^2-r_1^2}{2L})^2} h1=h2h1=h2h_1=h_2
  • 有了这个就可以算两圆相交的弧长了,但是需要先算出角度
这里写图片描述
这里写图片描述

用余弦公式可以算出angleaangleaangle_a和anglebanglebangle_b cos(anglea)=r21+L2−r222Lr1cos(anglea)=r12+L2−r222Lr1cos(angle_a)=\frac{r_1^2+L^2-r_2^2}{2Lr_1} cos(angleb)=r22+L2−r212Lr2cos(angleb)=r22+L2−r122Lr2cos(angle_b)=\frac{r_2^2+L^2-r_1^2}{2Lr_2} 但是实际相交的弧长所对应的圆心角是上述所求角的两倍,所以乘以2。 最后利用弧长公式即可计算两圆相交部分的弧长。 弧长=PiPiPi*对应圆心角(弧度制)

代码语言:javascript
复制
void CircleInterLen(circle a, circle b, double &la, double &lb) {
    double d = dist(a.centre, b.centre);//圆心距
    double t = (d*d + a.r*a.r - b.r*b.r) / (2.0 * d);//
    double h = sqrt((a.r*a.r) - (t*t)) * 2;//h1=h2
    double angle_a = 2 * acos((a.r*a.r + d*d - b.r*b.r) / (2.0 * a.r*d));  
    //余弦公式计算r1对应圆心角,弧度
    double angle_b = 2 * acos((b.r*b.r + d*d - a.r*a.r) / (2.0 * b.r*d));  
    //余弦公式计算r2对应圆心角,弧度
    la = angle_a*a.r;//r1所对应的相交弧长
    lb = angle_b*b.r;//r2所对应的相交弧长
    //double rest_la = 2.0 * PI * a.r - la;//r1圆剩余部分弧长
    //double rest_lb = 2.0 * PI * b.r - lb;//r2圆剩余部分弧长
}

剩下部分的弧长只需要用原来的弧长相减就行。

  • 再看相交部分的面积: 扇形面积公式:S=lr2S=lr2S=\frac{lr}{2}(l为弧长,r为半径)=nr22nr22\frac{nr^2}{2}(n为圆心角,弧度制) 相交部分面积包含扇形减去三角形的面积
这里写图片描述
这里写图片描述
代码语言:javascript
复制
void CircleInterArea(circle a, circle b,double &s1,double &s2) {
    double d = dist(a.centre, b.centre);//圆心距
    double t = (d*d + a.r*a.r - b.r*b.r) / (2.0 * d);//
    double h = sqrt((a.r*a.r) - (t*t)) * 2;//h1=h2
    double angle_a = 2 * acos((a.r*a.r + d*d - b.r*b.r) / (2.0 * a.r*d));  
    //余弦公式计算r1对应圆心角,弧度
    double angle_b = 2 * acos((b.r*b.r + d*d - a.r*a.r) / (2.0 * b.r*d));  
    //余弦公式计算r2对应圆心角,弧度
    double la = angle_a*a.r;//r1所对应的相交弧长
    double lb = angle_b*b.r;//r2所对应的相交弧长
    s1 = la*a.r / 2.0 - a.r*a.r*sin(angle_a) / 2.0; //相交部分r1圆的面积
    s2 = lb*b.r / 2.0 - b.r*b.r*sin(angle_b) / 2.0; //相交部分r2圆的面积
    double rest_s1 = PI*a.r*a.r - s1 - s2;//r1圆剩余部分面积,不含相交部分面积
    double rest_s2 = PI*b.r*b.r - s1 - s2;//r1圆剩余部分面积,不含相交部分面积
}

下面考虑两球相交:

这里写图片描述
这里写图片描述

相交部分如下:

这里写图片描述
这里写图片描述

但实际上,如果将其投影至平面,还是刚才的样子

这里写图片描述
这里写图片描述

从上可以知道,相交部分体积是两个球缺的和。 球冠面积S=2πrhS=2πrhS=2πrh 球缺的体积公式为V=πh2(r−h3)V=πh2(r−h3)V=πh^2(r-\frac{h}{3}) hhh球冠高 rrr球半径

两球心距离=LLL 半径分别为r1r2r1r2r_1 r_2 |r1−r2|<L<|r1+r2||r1−r2|<L<|r1+r2||r_1- r_2|< L< |r_1+ r_2| 两球相交的截面为平面,相交线为圆半径为r3r3r_3 截面到球心的距离分别为l1l2l1l2l_1 l_2 l1+l2=Ll1+l2=Ll_1+l_2=L LLL直线过相交圆心并垂直相交圆直径

r21=r23+l21r12=r32+l12r_1^2=r_3^2+l_1^2 r22=r23+l22r22=r32+l22r_2^2=r_3^2+l_2^2

r21−r22=l21−l22r12−r22=l12−l22r_1^2-r_2^2=l_1^2-l_2^2 r21−r22=(l1+l2)(l1−l2)r12−r22=(l1+l2)(l1−l2)r_1^2-r_2^2=(l_1+l_2)(l_1-l_2) r21−r22=(2l1−L)Lr12−r22=(2l1−L)Lr_1^2-r2^2=(2l_1-L)L l1=[(r21−r22)/L+L]/2l1=[(r12−r22)/L+L]/2l_1=[(r_1^2-r_2^2)/L+L]/2 l2=L−l1l2=L−l1l_2=L-l_1

x1=r1−l1x1=r1−l1x_1=r_1-l_1 x2=r2−l2x2=r2−l2x_2=r_2-l_2

代码语言:javascript
复制
typedef struct point {
    double x,y,z;
    point() {

    }
    point(double a, double b,double c) {
        x = a;
        y = b;
        z = c;
    }
    point operator -(const point &b)const {     //返回减去后的新点
        return point(x - b.x, y - b.y,z-b.z);
    }
    point operator +(const point &b)const {     //返回加上后的新点
        return point(x + b.x, y + b.y,z+b.z);
    }
    //数乘计算
    point operator *(const double &k)const {    //返回相乘后的新点
        return point(x * k, y * k,z*k);
    }
    point operator /(const double &k)const {    //返回相除后的新点
        return point(x / k, y / k,z/k);
    }
    double operator *(const point &b)const {    //点乘
        return x*b.x + y*b.y+z*b.z;
    }
}point;
double dist(point p1, point p2) {       //返回平面上两点距离
    return sqrt((p1 - p2)*(p1 - p2));
}
typedef struct sphere {//球
    double r;
    point centre;
}sphere;
void SphereInterVS(sphere a, sphere b,double &v,double &s) {
    double d = dist(a.centre, b.centre);//球心距
    double t = (d*d + a.r*a.r - b.r*b.r) / (2.0 * d);//
    double h = sqrt((a.r*a.r) - (t*t)) * 2;//h1=h2,球冠的高
    double angle_a = 2 * acos((a.r*a.r + d*d - b.r*b.r) / (2.0 * a.r*d));  //余弦公式计算r1对应圆心角,弧度
    double angle_b = 2 * acos((b.r*b.r + d*d - a.r*a.r) / (2.0 * b.r*d));  //余弦公式计算r2对应圆心角,弧度
    double l1 = ((a.r*a.r - b.r*b.r) / d + d) / 2;
    double l2 = d - l1;
    double x1 = a.r - l1, x2 = b.r - l2;//分别为两个球缺的高度
    double v1 = PI*x1*x1*(a.r - x1 / 3);//相交部分r1圆所对应的球缺部分体积
    double v2 = PI*x2*x2*(b.r - x2 / 3);//相交部分r2圆所对应的球缺部分体积
     v = v1 + v2;//相交部分体积
    double s1 = PI*a.r*x1;  //r1对应球冠表面积
    double s2 = PI*a.r*x2;  //r2对应球冠表面积
     s = 4 * PI*(a.r*a.r + b.r*b.r) - s1 - s2;//剩余部分表面积
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年08月13日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档