我有一个三维的二维平面: x+y+z=1,我想生成平面上的随机点(x,y,z)。如何选择这些点,使它们均匀分布?
发布于 2015-03-30 11:05:59
问题
如评论中所述,这一问题列于“具体规定”之下。尽管如此,这还是一个有趣的问题。因为没有分发我刚选了一个。以下是更精确的/general(?)问题我会回答:
假设我在
R^3
中有一个由ax + by + cz = d
定义的平面ax + by + cz = d
。 让c
位于最接近原点的P
上。 怎样才能在P
上统一地选择c
半径内的一个点?
算法
让n = (a,b,c)
。n
是P
的法线向量。
方向
ax + by + cz = d
上生成任意非零向量,称之为w
.你可以用n
的交叉乘积和任何非零向量,而不是平行于n
,来实现这一点。w
中以随机角度旋转n
。您可以使用formula来完成这个任务。direction = direction / direction.magnitude
射线起源
d
是0,我们就完了。否则: origin of the ray = vector3.zero + c * ( n )
刻度=random.range(最小,最大)
所以重点是
“守则”
这里是我的C实现算法。我从头到尾写了所有的矢量机器,所以有点混乱。我还没有对此进行彻底的测试。
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
typedef struct {
double x, y, z;
} vec3;
vec3 vec(double x, double y, double z);
vec3 crossp(vec3 u, vec3 v);
vec3 add(vec3 u, vec3 v);
double dotp(vec3 u, vec3 v);
double norm2(vec3 u);
double norm(vec3 u);
vec3 scale(vec3 u, double s);
vec3 normalize(vec3 u);
void print_vec3(vec3 u);
// generates a random point on the plane ax + by + cz = d
vec3 random_on_plane(double r, double a, double b, double c, double d) {
// The normal vector for the plane
vec3 n = vec(a, b, c);
// create a normal vector on the plane ax + by + cz = 0
// we take any vector not parallel to n
// and find the cross product
vec3 w;
if (n.x == 0)
w = crossp(n, vec(1,0,0));
else
w = crossp(n, vec(0,0,1));
// rotate the vector around n by a random angle
// using Rodrigues' rotation formula
// http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
double theta = ((double)rand() / RAND_MAX) * M_PI;
vec3 k = normalize(n);
w = add(scale(w, cos(theta)),
scale(crossp(k, w), sin(theta)));
// Scale the vector fill our disk.
// If the radius is zero, generate unit vectors
if (r == 0) {
w = scale(w, r/norm(w));
} else {
double rand_r = ((double)rand() / RAND_MAX) * r;
w = scale(w, rand_r/norm(w));
}
// now translate the vector from ax + by + cz = 0
// to the plane ax + by + cz = d
// http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_plane
if (d != 0) {
vec3 t = scale(n, d / norm2(n));
w = add(w, t);
}
return w;
}
int main(void) {
int i;
srand(time(NULL));
for (i = 0; i < 100; i++) {
vec3 r = random_on_plane(10, 1, 1, 1, 1);
printf("random v = ");
print_vec3(r);
printf("sum = %f, norm = %f\n", r.x + r.y + r.z, norm(r));
}
}
vec3 vec(double x, double y, double z) {
vec3 u;
u.x = x;
u.y = y;
u.z = z;
return u;
}
vec3 crossp(vec3 u, vec3 v) {
vec3 w;
w.x = (u.y * v.z) - (u.z * v.y);
w.y = (u.z * v.x) - (u.x * v.z);
w.z = (u.x * v.y) - (u.y * v.x);
return w;
}
double dotp(vec3 u, vec3 v) {
return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
}
double norm2(vec3 u) {
return dotp(u, u);
}
double norm(vec3 u) {
return sqrt(norm2(u));
}
vec3 scale(vec3 u, double s) {
u.x *= s;
u.y *= s;
u.z *= s;
return u;
}
vec3 add(vec3 u, vec3 v) {
u.x += v.x;
u.y += v.y;
u.z += v.z;
return u;
}
vec3 normalize(vec3 u) {
return scale(u, 1/norm(u));
}
void print_vec3(vec3 u) {
printf("%f %f %f\n", u.x, u.y, u.z);
}
发布于 2015-03-30 08:21:08
Eugene几乎是正确的:在区间[0,1]上生成两个随机数,称它们为A,B,然后x= min(A,B),y= max(A,B) - x,z=1- (x + y)。基本上,你在[0,1]线上选择两个点,而你的三个坐标是这两个点定义的三个区间。
发布于 2015-03-30 08:15:21
我先给你一个简单的算法
x = rand()
y = rand()
z = 1 - x - y
现在让我们看看该算法的一个实现。
此代码将生成任意类型的数字( +ve或-ve )
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
srand(time(NULL));
int x= ( rand() - rand() ) ;
int y= ( rand() - rand() ) ;
int z=1-x-y;
printf("x=%d y=%d z=%d",x,y,z);
}
只需使用srand()
创建随机数生成器,并使用rand()
分配随机数。
如果需要创建带有范围的随机数,则使用rand() % ( maxnumber + 1 )
,其中maxnumber是所需的最大值。
如果你希望你所有的数字都是正数,那就试试这个。
int main()
{
srand(time(NULL));
int x, y , z = -1;
while ( z < 0 )
{
x = rand() ;
y = rand() ;
z = 1 - (x + y );
}
printf("x=%d y=%d z=%d",x,y,z);
}
警告
上面的代码可能需要一些时间来执行,所以不要期望立即得到结果。
https://stackoverflow.com/questions/29350965
复制