我一直试图仅使用光盘的位置和法线在3D空间中沿着2D光盘的环(包括平移和旋转)生成点。
我一直在使用以下代码生成点并在Matlab中测试它(但将在c#中使用它)来检查点是否正确生成,但它似乎并不是正确地生成点。
numPoints = 25;
radius = 1;
pos = [1; 2; 3];
dir = normc([3; 4; 6]); % normalised
function [pointsT, points] = GenerateDiscPoints(numPoints, radius, pos, dir)
points = zeros(numPoints, 3);
pointsT = zeros(numPoints, 3);
% Angle between points
angle = 2 * pi / numPoints;
for i = 1:numPoints+1
% Current point angle
theta = angle * i;
% Generate point in flat disc (y is vertical axis in Unity)
x = radius * cos(theta) + pos(1);
y = 0 + pos(2);
z = radius * sin(theta) + pos(3);
% Save points
points(i, 1) = x;
points(i, 2) = y;
points(i, 3) = z;
% Calculate t value to translate points
t = (dir(1) * pos(1) - dir(1) * x + dir(2) * pos(2) - dir(2) * y + dir(3) * pos(3) - dir(3) * z) / (dir(1)*dir(1) + dir(2)*dir(2) + dir(3)*dir(3));
% Translate points to correct location
xT = x + t*dir(1);
yT = y + t*dir(2);
zT = z + t*dir(3);
% Save translated points
pointsT(i, 1) = xT;
pointsT(i, 2) = yT;
pointsT(i, 3) = zT;
end
% Plot
figure;
hold all;
grid on;
scatter3(points(:,1), points(:,2), points(:,3), 25, 'r');
scatter3(pointsT(:,1), pointsT(:,2), pointsT(:,3), 25, 'g');
p3 = line([pos(1) pos(1)+dir(1)], [pos(2) pos(2)+dir(2)], [pos(3) pos(3)+dir(3)]);
set(p3, 'Color', 'blue');
end
蓝线是光盘的法线,红点是翻译前的点,绿点是翻译后的点。在我看来,翻译的点似乎并没有在指定正常的光盘中生成。
我目前的算法出了什么问题?有什么更好的方法呢?
答案 0 :(得分:1)
沿着dir
方向的简单线性平移是不够的 - 你最终会得到pos
平面上圆圈的投影,而dir
正常{{ 1}},即椭圆。
你可以:
使用四元数构建旋转矩阵,将生成的圆圈重新定位到dir
。
或
在pos
处构建正交基础,其中一个轴为dir
。
简单的方法:
检查X轴是否与dir
平行 - 理想情况下是abs(dot(dir, X)) < 0.8
(假设两者都已归一化),因此它们彼此不太接近
如果(1)为真,则选择dir2 = Y
,否则dir2 = X
。
要创建第一个基础向量A = normalize(cross(dir, dir2))
。
创建第二个B = cross(dir, A)
。
现在,您可以按theta
pos + radius * (A * cos(theta) + B * sin(theta))
的每个值生成点数(以矢量表示法)。