简体   繁体   English

如何有效地确定两个平行向量的比例因子?

[英]How do I efficiently determine the scale factor of two parallel vectors?

I have two three-dimensional non-zero vectors which I know to be parallel, and thus I can multiply each component of one vector by a constant to obtain the other. 我有两个三维非零向量,我知道它是平行的,因此我可以将一个向量的每个分量乘以常数以获得另一个。 In order to determine this constant, I can take any of the fields from both vectors and divide them by one another to obtain the scale factor. 为了确定这个常数,我可以从两个向量中取出任何字段并将它们相互分开以获得比例因子。

For example: 例如:

vec3 vector1(1.0, 1.5, 2.0);
vec3 vector2(2.0, 3.0, 4.0);
float scaleFactor = vector2.x / vector1.x; // = 2.0

Unfortunately, picking the same field (say the x-axis) every time risks the divisor being zero. 不幸的是,每次选择相同的字段(比如x轴)都会使除数为零。

Dividing the lengths of the vectors is not possible either because it does not take a negative scale factor into account. 划分矢量的长度是不可能的,因为它不考虑负比例因子。

Is there an efficient means of going about this which avoids zero divisions? 是否有一种有效的方法可以避免零分割?

So we want something that: 所以我们想要一些东西:

1- has no branching 1-没有分支

2- avoids division by zero 2-避免被零除

3- ensures the largest possible divider 3-确保最大可能的分配器

These requirements are achieved by the ratio of two dot-products: 这些要求是通过两个点积的比例来实现的:

(v1 * v2) / (v2 * v2)
= 
(v1.x*v2.x + v1.y*v2.y + v1.z*v2.z) / (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z)

In the general case where the dimension is not a (compile time) constant, both numerator and denominator can be computed in a single loop. 在维度不是(编译时)常量的一般情况下,分子和分母都可以在单个循环中计算。

Pretty much, this. 差不多,这个。

inline float scale_factor(const vec3& v1, const vec3& v2, bool* fail)
{
    *fail = false;
    float eps = 0.000001;
    if (std::fabs(vec1.x) > eps)
        return vec2.x / vec1.x;
    if (std::fabs(vec1.y) > eps)
        return vec2.y / vec1.y;
    if (std::fabs(vec1.z) > eps)
        return vec2.z / vec1.z;

    *fail = true;
    return -1;
}

Also, one can think of getting 2 sums of elements, and then getting a scale factor with a single division. 此外,人们可以考虑获得2个元素的总和,然后通过单个部分获得比例因子。 You can get sum effectively by using IPP's ippsSum_32f, for example, as it is calculated using SIMD instructions. 例如,您可以使用IPP的ippsSum_32f有效地获得总和,因为它是使用SIMD指令计算的。

But, to be honest, I doubt that you can really improve these methods. 但是,说实话,我怀疑你能真正改进这些方法。 Either sum all -> divide or branch -> divide will provide you with the solution pretty close to the best. 无论是全部 - >除法还是分支 - >除法将为您提供非常接近最佳的解决方案。

To minimize the relative error, use the largest element: 要最小化相对错误,请使用最大元素:

if (abs(v1.x) > abs(v1.y) && abs(v1.x) > abs(v1.z))
    return v2.x / v1.x;
else if (abs(v1.y) > abs(v1.x) && abs(v1.y) > abs(v1.z))
    return v2.y / v1.y;
else
    return v2.z / v1.z;

This code assumes that v1 is not a zero vector. 此代码假定v1不是零向量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM