考虑以下问题 - 我给出了2个长度为L0和L1的链接。 P0是第一个链接开始的点,P1是我希望第二个链接的结束位于3-D空间的点。我应该编写一个函数,它应该将这些3-D点(P0和P1)作为输入,并且应该找到将第二个链接的终点置于P1的所有链接配置。
我对如何理解它的理解是 - 每个链接L0和L1将围绕自身创建一个球体S0和S1。我应该找出这两个球体的交点(它将是一个圆圈)并打印出该圆周上的所有点。
我在Finding intersection points between 3 spheres看到了gmatt的第一个回复,但由于图片没有显示,所以无法正确理解。我还看到了在http://mathworld.wolfram.com/Sphere-SphereIntersection.html
找到交叉点的公式我可以通过mathworld上给出的方法找到交点半径。此外,我可以找到该圆的中心,然后使用圆的参数方程来找到点。我唯一的疑问是这个方法适用于上面提到的P0和P1点吗?
请发表评论并告诉我您的想法。
答案 0 :(得分:2)
可以写出两个球体的方程式:
<X-P0,X-P0> - L0^2 = 0 (Eq0)
<X-P1,X-P1> - L1^2 = 0 (Eq1)
其中<U,V>
表示点积。如果定义,交叉圆的中心是线P0,P1和由Eq0-Eq1
定义的平面(圆的支撑)之间的交点。这个平面被称为两个球体的基础平面。该平面的方程是(E)=(Eq0) - (Eq1):
<P0,P0> - <P1,P1> + 2*<X,P1-P0> - L0^2 + L1^2 = 0 (E)
在线P0上表示点,P1由X(a)= a * P0 +(1-a)* P1表示,并且在(E)中注入以获得a中的线性方程。解是a0,圆的中心是C = X(a0)。注意,C可以在段P0,P1之外(当一个球的中心在另一个球的内部时)。我们得到:
2*a0 = 1 - (L0^2-L1^2)/dist(P0,P1)^2
然后获得圆的半径r
求解:
dist(C,P0)^2+r^2=L0^2, or equivalently
dist(C,P1)^2+r^2=L1^2
如果球体没有交叉点,它可能没有解决方案。
答案 1 :(得分:0)
我附上解决方案的代码。 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;
}