9

我试图找到一个点在单位球体表面上跳过不同点的轨迹的参数方程,使得:

  1. 每次跳跃都很小(pi/4 < d < pi/2),并且间隔很窄,例如 [1.33, 1.34]
  2. 该点尽可能快且均匀地访问球体的大部分区域
  3. 点沿“方向向量”传播,尽可能不同

这是我尝试过的

N = 3600;    % number of points
t = (1:N) * pi / 180;    % parameter
theta_sph = sqrt(2) * t * pi;    % first angle
phi_sph = sqrt(3) * t * pi;    % second angle
rho_sph = 1;    % radius
% Coordinates of a point on the surface of a sphere
x_sph = rho_sph * sin(phi_sph) .* cos(theta_sph);
y_sph = rho_sph * sin(phi_sph) .* sin(theta_sph);
z_sph = rho_sph * cos(phi_sph);

% Check length of jumps (it is intended that this is valid only for small jumps!!!)
aa = [x_sph(1:(N-1)); y_sph(1:(N-1)); z_sph(1:(N-1))];
bb = [x_sph(2:N); y_sph(2:N); z_sph(2:N)];
cc = cross(aa, bb);
d = rho_sph * atan2(arrayfun(@(n) norm(cc(:, n)), 1:size(cc,2)), dot(aa, bb));
figure
plot(d, '.')
figure
plot(diff(d), '.')

% Check trajectory on the surface of the sphere
figure
hh = 1;
h_plot3 = plot3(x_sph(hh), y_sph(hh), z_sph(hh), '-');
hold on
axis square
% axis off
set(gca, 'XLim', [-1 1])
set(gca, 'YLim', [-1 1])
set(gca, 'ZLim', [-1 1])
for hh = 1:N
  h_point3 = plot3(x_sph(hh), y_sph(hh), z_sph(hh), ...
      'o', 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'r');
  drawnow
  delete(h_point3)
  set(h_plot3, 'XData', x_sph(1:hh))
  set(h_plot3, 'YData', y_sph(1:hh))
  set(h_plot3, 'ZData', z_sph(1:hh))
end

编辑 -->任何人都可以找到更规则的轨迹,可能更快地覆盖球体(即跳跃次数最少)并且更均匀吗?从某种意义上说,它应该平稳地改变方向,而不是急剧地改变方向。审美是一种奖励。这些点应尽可能均匀地分布在球体表面上。

4

5 回答 5

2

Modifying the beginning of your code to introduce a rotation of the underlying sphere. This gives a trajectory that does not return to the poles as frequently. It may take some tuning of the rotation speeds to look "nice" (and it probably looks better when it is only rotating around one axis, not all 3). rot_angle1 is rotation around the x-axis, and rot_angle2 and rot_angle3 are rotation around the y and z axes. Maybe this gives you an idea at least!

N = 3600;    % number of points
t = (1:N) * pi / 180;    % parameter
theta_sph = sqrt(2) * t * pi;    % first angle
phi_sph = sqrt(3) * t * pi;    % second angle
rho_sph = 1;    % radius
rot_angle1 = sqrt(2) * t * pi;
rot_angle2 = sqrt(2.5) * t * pi;
rot_angle3 = sqrt(3) * t * pi;
% Coordinates of a point on the surface of a sphere
x_sph0 = rho_sph * sin(phi_sph) .* cos(theta_sph);
y_sph0 = rho_sph * sin(phi_sph) .* sin(theta_sph);
z_sph0 = rho_sph * cos(phi_sph);

x_sph1 = x_sph0;
y_sph1 = y_sph0.*cos(rot_angle1)-z_sph0.*sin(rot_angle1);
z_sph1 = y_sph0.*sin(rot_angle1)+z_sph0.*cos(rot_angle1);

x_sph2 = x_sph1.*cos(rot_angle2)+z_sph1.*sin(rot_angle2);
y_sph2 = y_sph1;
z_sph2 = -x_sph1.*sin(rot_angle2)+z_sph1.*cos(rot_angle2);

x_sph = x_sph2.*cos(rot_angle3)-y_sph2.*sin(rot_angle3);
y_sph = x_sph2.*sin(rot_angle3)+y_sph2.*cos(rot_angle3);
z_sph = z_sph2;
于 2013-11-01T02:16:45.430 回答
1

我手边没有 matlab 的副本,但我会发布我对你的曲线所做的修改。

只是要清楚,因为球面角有 n-finity+1 个不同的定义。我将使用以下内容,它与您的定义相反,但如果我尝试切换,我一定会犯错误。

  • \phi- 与 z 轴的角度
  • \theta- 在 xy 平面上的投影角度。

参数化

t为从 0 到 pi(含)的 N 个均匀分布的点的离散集合。

\phi(t) = t
\theta = 2 * c * t

相当直接和简单,围绕球体的螺旋线在\phi和中是线性的thetac是一个常数,表示 中的完整旋转次数\theta,它不必是整数。

相邻点

在您的示例中,您计算​​向量之间的角度atan2(norm(cross....)很好,但没有深入了解问题。你的问题是在一个球体的表面上,使用这个事实。所以我使用这个公式考虑点之间的距离

现在你找到了相邻的点,这些点发生在t +- dt并且theta +- 2pi无论发生什么。

在第一种情况下t +- dt,很容易计算cos(gamma) = 1 - 2 c^2 sin^2(t) dt^2。这种sin^2(t)依赖性是两极更密集的原因。理想情况下,您希望选择theta(t)并且满足phi(t)这种dtheta^2 * sin^2(phi)情况的恒定且最小的。

第二种情况有点困难,并提出了我关于“惊人”你的观点的评论。如果我们选择一个dtheta不均匀划分 2pi 的 N,那么在thetaI 中围绕球体完全旋转后,不能直接在前一点下方结束。在这种情况下,要比较点之间的距离,请使用delta tso that c delta t = 1。然后你有delta phi = delta tdelta theta = 2 c delta t - 2pi。根据您对 的选择cdelta phi可能会或可能不会小到足以使用小角度近似值。

最后的笔记

很明显,这c=0是一条沿着球体的直线。通过增加c,您可以增加“螺旋密度”,从而获得更多覆盖。但是,您也会增加相邻点之间的距离。您将需要为所选内容选择一个c,以N使上述两个距离公式大致相等。

EDIT 将一些东西移到 mathbin 以保持清洁

于 2013-11-01T05:23:23.940 回答
0
clear all
close all

u = pi/2:(-pi/36):-pi/2;
v = 0:pi/36:2*pi;

nv = length(v);
nu = length(u);

f = myfigure(1);
ax = myaxes(f,1,1);

hold on

for aa = 1:nv
    tv = v(aa);
    for bb = 1:nu
        tu = u(bb);
        x = sin(tu)*cos(tv);
        y = cos(tu)*cos(tv);
        z = sin(tv);
        plot3(x,y,z,'*')
    end
end

edit: myfigure and myaxes are functions I have for creating a figure and an axes

于 2013-11-06T07:20:15.673 回答
0

我已经用 C 编写了一个快速版本,它在给定固定点数的情况下表现得非常好。你可以在ideone玩它。如果您有启用 WebGL 的浏览器(Chrome、Firefox),您可以将这些结果粘贴到此处以查看它们的绘图。由于推导公式时使用了一些积分近似,极点有点偏离,但除此之外很难看出缺陷。除了您希望输出的点数之外,没有需要调整的常量。

#include <stdio.h>
#include <math.h>

int main(void) {
    int i, numPoints = 200;
    double slope = sqrt(1.2) / sqrt(numPoints);
    for (i = 0; i < numPoints; i++) {
        double s = asin((double)i / (double)(numPoints - 1) * 2.0 - 1.0);
        double z = sin(s);
        double r = sqrt(1.0 - z * z);
        double ss = (2.0 * s + M_PI) / slope;
        double x = cos(ss) * r;
        double y = sin(ss) * r;
        printf("%lf,%lf,%lf,\"1\"\n", x, y, z);
    }
    return 0;
}
于 2013-11-07T23:24:47.557 回答
0

我在这里编辑,因为它是一个长代码。在大卫和卡尔哈特的提示之后,我尝试了这个:

N = 3600;    % number of points
t = (1:N) * pi / 180;    % parameter
% theta_sph much faster than phi_sph to avoid overly visiting the poles
theta_sph = sqrt(20.01) * t * pi;    % first angle
phi_sph = sqrt(.02) * t * pi;    % second angle
rho_sph = 1;    % radius
% Coordinates of a point on the surface of a sphere
x_sph0 = rho_sph * sin(phi_sph) .* cos(theta_sph);
y_sph0 = rho_sph * sin(phi_sph) .* sin(theta_sph);
z_sph0 = rho_sph * cos(phi_sph);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Use David's hint to rotate axes (but only the first now):
rot_angle1 = t * pi / 10;
rot_angle2 = 0;
rot_angle3 = 0;

x_sph1 = x_sph0;
y_sph1 = y_sph0.*cos(rot_angle1)-z_sph0.*sin(rot_angle1);
z_sph1 = y_sph0.*sin(rot_angle1)+z_sph0.*cos(rot_angle1);

x_sph2 = x_sph1.*cos(rot_angle2)+z_sph1.*sin(rot_angle2);
y_sph2 = y_sph1;
z_sph2 = -x_sph1.*sin(rot_angle2)+z_sph1.*cos(rot_angle2);

x_sph = x_sph2.*cos(rot_angle3)-y_sph2.*sin(rot_angle3);
y_sph = x_sph2.*sin(rot_angle3)+y_sph2.*cos(rot_angle3);
z_sph = z_sph2;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Check length of jumps
aa = [x_sph(1:(N-1)); y_sph(1:(N-1)); z_sph(1:(N-1))];
bb = [x_sph(2:N); y_sph(2:N); z_sph(2:N)];
cc = cross(aa, bb);
d = rho_sph * atan2(arrayfun(@(n) norm(cc(:, n)), 1:size(cc,2)), dot(aa, bb));
figure
plot(d, '.')

% Check trajectory on the surface of the sphere
figure
hh = 1;
h_plot3 = plot3(x_sph(hh), y_sph(hh), z_sph(hh), '-');
hold on
axis square
% axis off
set(gca, 'XLim', [-1 1])
set(gca, 'YLim', [-1 1])
set(gca, 'ZLim', [-1 1])
for hh = 1:N
  h_point3 = plot3(x_sph(hh), y_sph(hh), z_sph(hh), ...
      'o', 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'r');
  drawnow
  delete(h_point3)
  set(h_plot3, 'XData', x_sph(1:hh))
  set(h_plot3, 'YData', y_sph(1:hh))
  set(h_plot3, 'ZData', z_sph(1:hh))
end

我觉得比以前好多了!我发现有两件事很重要: 1. theta_sph 必须比 phi_sph 快得多,以避免过于频繁地访问两个相反的极点;2. 如果 theta_sph 比 phi_sph 快,那么你必须在 rot_angle1 或 rot_angle2 上缓慢旋转以获得不太混乱的轨迹。我仍然愿意接受任何其他提示来改善结果。

于 2013-11-01T05:06:26.177 回答