在C中的特定平面中生成随机点

问题描述 投票:3回答:3

我有一个三维的2D平面:x + y + z = 1,我想在平面上生成随机点(x,y,z)。如何选择这些点以使它们均匀分布?

c algorithm
3个回答
5
投票

问题

如评论中所述,问题尚未明确。尽管这是一个有趣的问题。因为没有给出分配我只选了一个。以下是我将回答的更精确的(?)/一般(?)问题:

假设我在P定义的R^3中有一架ax + by + cz = d飞机。

c在距离原点最近的P上。

如何在P的某个半径r内统一选择c上的一个点?

算法

让qazxsw poi。 qazxsw poi是qazxsw poi的正常向量。

direction

  1. 在平面n = (a,b,c)上生成任何非零向量,称之为n。您可以通过将P的任意积分与任何与ax + by + cz = d不平行的非零向量相乘来实现此目的。
  2. 在qazxsw poi中随机旋转qazxsw poi周围的qazxsw poi。你可以使用w来做到这一点。
  3. 所以,现在你通过规范化来获得方向
n

origin of the ray

  1. 如果n为0,我们就完成了。除此以外:
  2. 计算c = Vector3的平面距离(0,0,0) 根据w
  3. 翻译光线的原点
n

scale = random.range(min,max)

So the point is

  • origin_of_the_ray + scale *(direction_)

代码

这是我的算法的C实现。我从头开始编写了所有的矢量机器,所以它有点乱。我没有彻底测试过这个。

[0,2pi)

2
投票

Eugene几乎是正确的:在区间[0,1]上生成两个随机数,称之为A,B。然后x = min(A,B),y = max(A,B) - x,z = 1 - (x + y)。基本上,您在线[0,1]上选择两个点,并且您的三个坐标是由这两个点定义的三个区间。


1
投票

我先给你一个简单的算法

http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula

现在让我们看看该算法的实现

此代码将生成任何类型的数字(+ ve或-ve)

direction = direction  /  direction.magnitude

只需使用d为随机数生成器播种,并使用http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_plane分配随机数。

如果您需要创建具有范围的随机数,请使用 origin of the ray = vector3.zero + c * ( n ) ,其中maxnumber是您想要的最大值。

如果您希望所有数字都是正数,那么试试这个

#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);
}

警告 上面的代码可能需要一些时间来执行,所以不要指望即时结果

© www.soinside.com 2019 - 2024. All rights reserved.