gpt4 book ai didi

c++ - Gram-Schmidt 正交化不正确的实现

转载 作者:行者123 更新时间:2023-11-30 04:25:14 25 4
gpt4 key购买 nike

我正在构建一个基于 OpenGL3 的免费开源 3D 游戏引擎(这不是学校作业,而是为了个人技能发展和回馈开源社区)。我已经到了需要学习大量相关数学的阶段,所以我正在阅读一本很棒的教科书,名为“3D 游戏编程和计算机图形学数学,第 3 版”。

虽然我在尝试做本书的练习时遇到了麻烦,因为我尝试在 C++ 中实现“Gram-Schmidt 正交算法”时输出了错误的答案。我不是数学专家(尽管我正在努力变得更好),而且我在研究数学算法并将其转化为代码方面的经验非常有限(仅限于我从 Udacity.com 学到的一些东西)。无论如何,如果有人可以查看我的错误代码并给我提示或解决方案,那将非常有帮助。

这里是:

/*
The Gram-Schmidt Orthogonalization algorithm is as follows:

Given a set of n linearly independent vectors Beta = {e_1, e_2, ..., e_n},
the algorithm produces a set Beta' = {e_1', e_2', ..., e_n'} such that
dot(e_i', e_j') = 0 whenever i != j.

A. Set e_1' = e_1
B. Begin with the index i = 2 and k = 1
C. Subtract the projection of e, onto the vectors e_1', e_2', ..., e_(i-1)'
from e_i, and store the result in e_i', That is,

dot(e_i, e_k')
e_i' = e_i - sum_over(-------------- e_k')
e_k'^2

D. If i < n, increment i and loop back to step C.
*/

#include <iostream>
#include <glm/glm.hpp>

glm::vec3 sum_over_e(glm::vec3* e, glm::vec3* e_prime, int& i)
{
int k = 0;
glm::vec3 result;

while (k < i-2)
{
glm::vec3 e_prime_k_squared(pow(e_prime[k].x, 2), pow(e_prime[k].y, 2), pow(e_prime[k].z, 2));
result += (glm::dot(e[i], e_prime[k]) / e_prime_k_squared) * e_prime[k];
k++;
}

return result;
}

int main(int argc, char** argv)
{
int n = 2; // number of vectors we're working with
glm::vec3 e[] = {
glm::vec3(sqrt(2)/2, sqrt(2)/2, 0),
glm::vec3(-1, 1, -1),
glm::vec3(0, -2, -2)
};

glm::vec3 e_prime[n];
e_prime[0] = e[0]; // step A

int i = 0; // step B

do // step C
{
e_prime[i] = e[i] - sum_over_e(e, e_prime, i);

i++; // step D
} while (i-1 < n);

for (int loop_count = 0; loop_count <= n; loop_count++)
{
std::cout << "Vector e_prime_" << loop_count+1 << ": < "
<< e_prime[loop_count].x << ", "
<< e_prime[loop_count].y << ", "
<< e_prime[loop_count].z << " >" << std::endl;
}

return 0;
}

这段代码输出:

Vector e_prime_1: < 0.707107, 0.707107, 0 >
Vector e_prime_2: < -1, 1, -1 >
Vector e_prime_3: < 0, -2, -2 >

但正确答案应该是:

Vector e_prime_1: < 0.707107, 0.707107, 0 >
Vector e_prime_2: < -1, 1, -1 >
Vector e_prime_3: < 1, -1, -2 >

编辑:这是生成正确答案的代码:

#include <iostream>
#include <glm/glm.hpp>

glm::vec3 sum_over_e(glm::vec3* e, glm::vec3* e_prime, int& i)
{
int k = 0;
glm::vec3 result;

while (k < i-1)
{
float e_prime_k_squared = glm::dot(e_prime[k], e_prime[k]);
result += ((glm::dot(e[i], e_prime[k]) / e_prime_k_squared) * e_prime[k]);
k++;
}

return result;
}

int main(int argc, char** argv)
{
int n = 3; // number of vectors we're working with
glm::vec3 e[] = {
glm::vec3(sqrt(2)/2, sqrt(2)/2, 0),
glm::vec3(-1, 1, -1),
glm::vec3(0, -2, -2)
};

glm::vec3 e_prime[n];
e_prime[0] = e[0]; // step A

int i = 0; // step B

do // step C
{
e_prime[i] = e[i] - sum_over_e(e, e_prime, i);

i++; // step D
} while (i < n);

for (int loop_count = 0; loop_count < n; loop_count++)
{
std::cout << "Vector e_prime_" << loop_count+1 << ": < "
<< e_prime[loop_count].x << ", "
<< e_prime[loop_count].y << ", "
<< e_prime[loop_count].z << " >" << std::endl;
}

return 0;
}

最佳答案

问题可能在于您定义 e_k'^2 的方式。就 vector 数学而言, vector 的平方通常被视为其范数的平方。因此,

double e_prime_k_squared = glm::dot(e_prime_k, e_prime_k);

此外,除以 vector 是未定义的(我想知道为什么 GLM 允许这样做?),所以如果 e_k'^2 是 vector ,则整个事情是未定义的。

关于c++ - Gram-Schmidt 正交化不正确的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12254720/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com