3d 求两个球面的交点

3d 求两个球面的交点,3d,geometry,intersection,3d,Geometry,Intersection,考虑以下问题-我有两个长度为L0和L1的链接。P0是第一个链接开始的点,P1是我希望第二个链接的末端在三维空间中的点。我应该写一个函数,它应该把这些3-D点(P0和P1)作为输入,并且应该找到把第二个链接的端点放在P1的链接的所有配置 我对如何进行的理解是——每个链接L0和L1将在其自身周围创建一个球体S0和S1。我应该找出这两个球体(将是一个圆)的交点,并打印出该圆圆周上的所有点 我在网上看到了gmatt的第一个回复,但由于图像没有显示,我无法正确理解。我还看到了一个计算交叉点的公式 我可以用

考虑以下问题-我有两个长度为L0和L1的链接。P0是第一个链接开始的点,P1是我希望第二个链接的末端在三维空间中的点。我应该写一个函数,它应该把这些3-D点(P0和P1)作为输入,并且应该找到把第二个链接的端点放在P1的链接的所有配置

我对如何进行的理解是——每个链接L0和L1将在其自身周围创建一个球体S0和S1。我应该找出这两个球体(将是一个圆)的交点,并打印出该圆圆周上的所有点

我在网上看到了gmatt的第一个回复,但由于图像没有显示,我无法正确理解。我还看到了一个计算交叉点的公式

我可以用mathworld上给出的方法求交点半径。我还可以找到圆的中心,然后用圆的参数方程找到点。我唯一的疑问是,对于上面提到的点P0和P1,这种方法是否有效


请评论并让我知道您的想法。

两个球体的方程式可以写成:

<X-P0,X-P0> - L0^2 = 0 (Eq0)
<X-P1,X-P1> - L1^2 = 0 (Eq1)
用X(a)=a*P0+(1-a)*P1表示线P0、P1上的一个点,并注入(E)中以获得a中的线性方程。解为a0,圆心为C=X(a0)。请注意,C可能位于段P0、P1的外侧(当一个球体的中心位于另一个球体的内侧时)。我们得到:

然后,通过求解以下公式获得圆的半径
r

dist(C,P0)^2+r^2=L0^2, or equivalently
dist(C,P1)^2+r^2=L1^2

如果球体没有交点,它可能没有解。

我附上解的代码。P0被认为是一个肩部点,P1被认为是位于空间中的点(考虑到我上臂和前臂的长度,我应该抓住这个点)。请评论一下,让我知道你的想法

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

struct point {
     double x, y, z;
};

/*
 * Used to represent a vector in 
 * Xi + Yj + Zk format
 */
struct vector {
     double i, j, k;
};

/*
 * Used to represent a plane in 
 * Ax + By + Cz + D = 0 format
 */
struct plane {
     double A, B, C, D;
};

/*
 * Represents the final assembly of the configuration. When two spheres
 * intersect they form a circle whose center is stored at "center" and radius is
 * stored at "radius". The circle also has a support which is defined by a plane
 * called as "radical plane" and its equation is stored at "p".
 */
struct configuration {
     struct point center;
     double radius;
     struct plane p;
};

/* 
 * Conversion functions between vector and point
*/
struct vector get_vector_from_point(struct point p) {
     static struct vector v;
     v.i = p.x;
     v.j = p.y;
     v.k = p.z;
     return v;
}

struct point get_point_from_vector(struct vector v) {
     static struct point p;
     p.x = v.i;
     p.y = v.j;
     p.z = v.k;
     return p;
}

int check_if_same_points(struct point p1, struct point p2) {
     return ((p1.x == p2.x) && (p1.y == p2.y) && (p1.z == p2.z));
}
/*
 * Distance formula
 */
double distance(struct point p0, struct point p1) {
     return sqrt(pow((fabs(p1.z - p0.z)), 2) + pow((fabs(p1.y - p0.y)), 2) + pow((fabs(p1.x - p0.x)), 2));
}

/*
 * Customized utility functions used for vector mathematics
 */
double dot_product(struct vector p0, struct vector p1) {
     return (p0.i * p1.i + p0.j * p1.j + p0.k * p1.k);
}
struct vector scale_vector(double scale, struct vector v) {
     static struct vector scaled_vec;
     scaled_vec.i = scale * v.i;
     scaled_vec.j = scale * v.j;
     scaled_vec.k = scale * v.k;
     return scaled_vec;
}

struct vector add_vectors(struct vector v1, struct vector v2) {
     static struct vector v;
     v.i = v1.i + v2.i;
     v.j = v1.j + v2.j;
     v.k = v1.k + v2.k;
     return v;
}

struct vector subtract_vectors(struct vector v1, struct vector v2) {
     static struct vector v;
     v.i = v1.i - v2.i;
     v.j = v1.j - v2.j;
     v.k = v1.k - v2.k;
     return v;
}

/*
 * Takes the given assembly of points and links. Returns object of configuration
 * structure with necessary information. The center and radius from the returned
 * structure can be used find possible locations of elbow. 
 * Client can use following parametric equation of circle in 3-D
 * X(t) = C + r (cos(t) * U + sin(t) * V)
 * where 0 <= t < 2 * pie, C is the center, r is the radius, U and V are unit
 * normals to the plane such that if N is a unit length plane normal then
 * {U,V,N} are mutually orthogonal.
 */
struct configuration return_config(struct point p0, double l0, struct point p1, double l1) {

     struct vector p0_v = get_vector_from_point(p0);
     struct vector p1_v = get_vector_from_point(p1);

     double dot_prd_p0 = dot_product(p0_v, p0_v);
     double dot_prd_p1 = dot_product(p1_v, p1_v);

     struct vector sub_vec = subtract_vectors(p1_v, p0_v);
     double D = ((l0 * l0) - (l1 * l1) + dot_prd_p1 - dot_prd_p0) / 2.0f;

     static struct plane p;
     p.A = sub_vec.i; p.B = sub_vec.j; p.C = sub_vec.k; p.D = D;

     static struct configuration c;

     /*
      * Special case when object point and shoulder point are same.
      */
     if(check_if_same_points(p0, p1)) {
          printf("object and shoulder are at same location \n");
          c.center.x = p0.x; c.center.y = p0.y; c.center.z = p0.z;
          c.radius = l0;
          c.p.A = c.p.B = c.p.C = c.p.D = 0.0f;
          return c;
     }

     double a0 = (1.0f - (((l0 * l0) - (l1 * l1)) / (distance(p0, p1) * distance(p0, p1)))) / 2.0f;


     struct vector lhs = scale_vector(a0,p0_v);
     struct vector rhs = scale_vector(1.0f - a0, p1_v);
     struct vector ans = add_vectors(lhs, rhs);

     struct point center = get_point_from_vector(ans);
     double radius = sqrt((l0 * l0) - (distance(center, p0) * distance(center, p0)));

     c.center.x = center.x; c.center.y = center.y; c.center.z = center.z;
     c.radius = radius;
     c.p.A = p.A; c.p.B = p.B; c.p.C = p.C; c.p.D = D;
     return c;
}

/*
 * The logic is as follows - Point P0 generates a sphere of radius L0 around it,
 * P1 generates another sphere of radius L1 around it. The intersection(if any)
 * will be a circle with a plane. If I can return the center and radius of that
 * circle and equation of the plane, then the client can find out any possible
 * location of the elbow by varying the value of theta in the parametric
 * equation of the circle. Thus if the spheres meet to generate a circle then
 * there will be infinite elbow positions. If it does not generate a circle and
 * meet "externally" then there will be only single elbow position. Otherwise
 * there will be no solutions at all.
 */
int main() {

     struct point p0, p1;
     p0.x = 0, p0.y = 0, p0.z = 0;
     p1.x = 50, p1.y = 50, p1.z = 0;
     double l0 = 50, l1 = 50;

     printf("Shoulder coordinates : (%lf, %lf, %lf) \n", p0.x, p0.y, p0.z);
     printf("Object coordinates: (%lf, %lf, %lf) \n", p1.x, p1.y, p1.z);
     printf("link0 = %lf, link1 = %lf \n", l0, l1);

     if(distance(p0, p1) > (l0 + l1)) {
          printf("The given combination of the points and links cannot make a valid configuration");
          return -1;
     }
     struct configuration c = return_config(p0, l0, p1, l1);
     printf("Center = (%lf, %lf, %lf), radius = %lf \n", c.center.x, c.center.y, c.center.z, c.radius);
     printf("Equation of the radical plane = %lfA + (%lf)B + (%lf)C + %lf = 0 \n", c.p.A, c.p.B, c.p.C, c.p.D);
     return 0;
}
#包括
#包括
#包括
结构点{
双x,y,z;
};
/*
*用于表示中的向量
*席+YJ+ZK格式
*/
结构向量{
双i,j,k;
};
/*
*用于表示平面中的平面
*Ax+By+Cz+D=0格式
*/
结构平面{
双A、B、C、D;
};
/*
*表示配置的最终组装。当两个球体
*相交它们形成一个圆心存储在“中心”,半径为
*存储在“半径”处。圆还有一个由平面定义的支撑
*称为“根平面”,其方程存储在“p”处。
*/
结构配置{
结构点中心;
双半径;
结构平面p;
};
/* 
*向量与点之间的转换函数
*/
结构向量从点(结构点p)获取点向量{
静态结构向量v;
v、 i=p.x;
v、 j=p.y;
v、 k=p.z;
返回v;
}
结构点从向量中获取点(结构向量v){
静态结构点p;
p、 x=v.i;
p、 y=v.j;
p、 z=v.k;
返回p;
}
int检查点是否相同(结构点p1、结构点p2){
返回((p1.x==p2.x)和&(p1.y==p2.y)和&(p1.z==p2.z));
}
/*
*距离公式
*/
双距离(结构点p0、结构点p1){
返回sqrt(pow((fabs(p1.z-p0.z)),2)+pow((fabs(p1.y-p0.y)),2)+pow((fabs(p1.x-p0.x)),2));
}
/*
*用于向量数学的自定义实用函数
*/
双点积(结构向量p0,结构向量p1){
回报率(p0.i*p1.i+p0.j*p1.j+p0.k*p1.k);
}
结构向量比例\向量(双比例,结构向量v){
静态结构向量缩放向量;
标度向量i=标度*v.i;
标度向量j=标度*v.j;
缩放向量k=缩放*v.k;
返回缩放向量;
}
结构向量加法向量(结构向量v1,结构向量v2){
静态结构向量v;
v、 i=v1.i+v2.i;
v、 j=v1.j+v2.j;
v、 k=v1.k+v2.k;
返回v;
}
结构向量减去_向量(结构向量v1,结构向量v2){
静态结构向量v;
v、 i=v1.i-v2.i;
v、 j=v1.j-v2.j;
v、 k=v1.k-v2.k;
返回v;
}
/*
*获取点和链接的给定集合。返回配置的对象
*包含必要信息的结构。返回的曲面的中心和半径
*结构可用于查找弯头的可能位置。
*客户可以使用以下三维圆的参数方程
*X(t)=C+r(cos(t)*U+sin(t)*V)
*其中0(l0+l1)){
printf(“给定的点和链接组合不能构成有效配置”);
返回-1;
}
结构配置c=返回配置(p0、l0、p1、l1);
printf(“中心=(%lf,%lf,%lf),半径=%lf\n”,c.Center.x,c.Center.y,c.Center.z,c.radius);
printf(“根平面方程=%lfA+(%lf)B+(%lf)C+%lf=0\n”,C.p.A,C.p.B,C.p.C,C.p.D);
返回0;
}

FYI:修复了gmatt答案中的图像。非常感谢Eric的回复。我想我得到了解决方案,我将其作为一个答案发布。你不应该有不同的
向量
结构,除非它们是不同维度的。因为
本质上是一个
矢量
,即所谓的
半径矢量
,“起始”于原点,并“指向”所需的点。
dist(C,P0)^2+r^2=L0^2, or equivalently
dist(C,P1)^2+r^2=L1^2
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

struct point {
     double x, y, z;
};

/*
 * Used to represent a vector in 
 * Xi + Yj + Zk format
 */
struct vector {
     double i, j, k;
};

/*
 * Used to represent a plane in 
 * Ax + By + Cz + D = 0 format
 */
struct plane {
     double A, B, C, D;
};

/*
 * Represents the final assembly of the configuration. When two spheres
 * intersect they form a circle whose center is stored at "center" and radius is
 * stored at "radius". The circle also has a support which is defined by a plane
 * called as "radical plane" and its equation is stored at "p".
 */
struct configuration {
     struct point center;
     double radius;
     struct plane p;
};

/* 
 * Conversion functions between vector and point
*/
struct vector get_vector_from_point(struct point p) {
     static struct vector v;
     v.i = p.x;
     v.j = p.y;
     v.k = p.z;
     return v;
}

struct point get_point_from_vector(struct vector v) {
     static struct point p;
     p.x = v.i;
     p.y = v.j;
     p.z = v.k;
     return p;
}

int check_if_same_points(struct point p1, struct point p2) {
     return ((p1.x == p2.x) && (p1.y == p2.y) && (p1.z == p2.z));
}
/*
 * Distance formula
 */
double distance(struct point p0, struct point p1) {
     return sqrt(pow((fabs(p1.z - p0.z)), 2) + pow((fabs(p1.y - p0.y)), 2) + pow((fabs(p1.x - p0.x)), 2));
}

/*
 * Customized utility functions used for vector mathematics
 */
double dot_product(struct vector p0, struct vector p1) {
     return (p0.i * p1.i + p0.j * p1.j + p0.k * p1.k);
}
struct vector scale_vector(double scale, struct vector v) {
     static struct vector scaled_vec;
     scaled_vec.i = scale * v.i;
     scaled_vec.j = scale * v.j;
     scaled_vec.k = scale * v.k;
     return scaled_vec;
}

struct vector add_vectors(struct vector v1, struct vector v2) {
     static struct vector v;
     v.i = v1.i + v2.i;
     v.j = v1.j + v2.j;
     v.k = v1.k + v2.k;
     return v;
}

struct vector subtract_vectors(struct vector v1, struct vector v2) {
     static struct vector v;
     v.i = v1.i - v2.i;
     v.j = v1.j - v2.j;
     v.k = v1.k - v2.k;
     return v;
}

/*
 * Takes the given assembly of points and links. Returns object of configuration
 * structure with necessary information. The center and radius from the returned
 * structure can be used find possible locations of elbow. 
 * Client can use following parametric equation of circle in 3-D
 * X(t) = C + r (cos(t) * U + sin(t) * V)
 * where 0 <= t < 2 * pie, C is the center, r is the radius, U and V are unit
 * normals to the plane such that if N is a unit length plane normal then
 * {U,V,N} are mutually orthogonal.
 */
struct configuration return_config(struct point p0, double l0, struct point p1, double l1) {

     struct vector p0_v = get_vector_from_point(p0);
     struct vector p1_v = get_vector_from_point(p1);

     double dot_prd_p0 = dot_product(p0_v, p0_v);
     double dot_prd_p1 = dot_product(p1_v, p1_v);

     struct vector sub_vec = subtract_vectors(p1_v, p0_v);
     double D = ((l0 * l0) - (l1 * l1) + dot_prd_p1 - dot_prd_p0) / 2.0f;

     static struct plane p;
     p.A = sub_vec.i; p.B = sub_vec.j; p.C = sub_vec.k; p.D = D;

     static struct configuration c;

     /*
      * Special case when object point and shoulder point are same.
      */
     if(check_if_same_points(p0, p1)) {
          printf("object and shoulder are at same location \n");
          c.center.x = p0.x; c.center.y = p0.y; c.center.z = p0.z;
          c.radius = l0;
          c.p.A = c.p.B = c.p.C = c.p.D = 0.0f;
          return c;
     }

     double a0 = (1.0f - (((l0 * l0) - (l1 * l1)) / (distance(p0, p1) * distance(p0, p1)))) / 2.0f;


     struct vector lhs = scale_vector(a0,p0_v);
     struct vector rhs = scale_vector(1.0f - a0, p1_v);
     struct vector ans = add_vectors(lhs, rhs);

     struct point center = get_point_from_vector(ans);
     double radius = sqrt((l0 * l0) - (distance(center, p0) * distance(center, p0)));

     c.center.x = center.x; c.center.y = center.y; c.center.z = center.z;
     c.radius = radius;
     c.p.A = p.A; c.p.B = p.B; c.p.C = p.C; c.p.D = D;
     return c;
}

/*
 * The logic is as follows - Point P0 generates a sphere of radius L0 around it,
 * P1 generates another sphere of radius L1 around it. The intersection(if any)
 * will be a circle with a plane. If I can return the center and radius of that
 * circle and equation of the plane, then the client can find out any possible
 * location of the elbow by varying the value of theta in the parametric
 * equation of the circle. Thus if the spheres meet to generate a circle then
 * there will be infinite elbow positions. If it does not generate a circle and
 * meet "externally" then there will be only single elbow position. Otherwise
 * there will be no solutions at all.
 */
int main() {

     struct point p0, p1;
     p0.x = 0, p0.y = 0, p0.z = 0;
     p1.x = 50, p1.y = 50, p1.z = 0;
     double l0 = 50, l1 = 50;

     printf("Shoulder coordinates : (%lf, %lf, %lf) \n", p0.x, p0.y, p0.z);
     printf("Object coordinates: (%lf, %lf, %lf) \n", p1.x, p1.y, p1.z);
     printf("link0 = %lf, link1 = %lf \n", l0, l1);

     if(distance(p0, p1) > (l0 + l1)) {
          printf("The given combination of the points and links cannot make a valid configuration");
          return -1;
     }
     struct configuration c = return_config(p0, l0, p1, l1);
     printf("Center = (%lf, %lf, %lf), radius = %lf \n", c.center.x, c.center.y, c.center.z, c.radius);
     printf("Equation of the radical plane = %lfA + (%lf)B + (%lf)C + %lf = 0 \n", c.p.A, c.p.B, c.p.C, c.p.D);
     return 0;
}