均匀地分布x点

问题描述 投票:0回答:5
i希望在一个圆圈内均匀地分布一组预定的点。通过统一的分布,我的意思是它们都应该彼此之间平等距离(因此,随机方法无法正常工作)。 我尝试了一种六角形方法,但是我在达到最外面的半径时始终遇到问题。 我的当前方法是嵌套的循环,其中每个外迭代都会降低半径和点数,每个内部循环均匀下降到新半径上。本质上,这是一堆嵌套的圆圈。不幸的是,它远非如此。关于如何正确执行此操作的任何提示?

Nested for-loop result在该区域内具有统一分布以及边界冲突的统一分布的目标;任何解决方案都将是两者之间的妥协。我用一个附加的参数

alpha
math geometry
5个回答
42
投票

alpha=0给出了典型的向日葵布置,带有锯齿状的边界:

边界更光滑:

alpha0(进一步增加alpha是有问题的:太多的点最终出现在边界上)。

算法放置

alpha=2

点,其中第三点位于距离边界的距离(索引始于
n

),并且以极角

kalpha2

sqrt(k-1/2)

k=1

,其中

2*pi*k/phi^2
是黄金比率。例外:最后一点点放置在圆的外边界上,并将其他点的极性半径缩放为解释。极性半径的计算是在函数
phi
中完成的。
它在
matlab
.
中进行了编码。
alpha*sqrt(n)

我的python翻译上也标记了公元。
radius

@olivelsaword上面建造,这是使用numpy的python实现:

function sunflower(n, alpha) % example: n=500, alpha=2 clf hold on b = round(alpha*sqrt(n)); % number of boundary points phi = (sqrt(5)+1)/2; % golden ratio for k=1:n r = radius(k,n,b); theta = 2*pi*k/phi^2; plot(r*cos(theta), r*sin(theta), 'r*'); end end function r = radius(k,n,b) if k>n-b r = 1; % put on the boundary else r = sqrt(k-1/2)/sqrt(n-(b+1)/2); % apply square root end end

9
投票



2
投票
求解(因此,所有信用to user3717023&matt)。 只需将我的翻译添加到这里,以防其他人需要:)

from math import sqrt, sin, cos, pi phi = (1 + sqrt(5)) / 2 # golden ratio def sunflower(n, alpha=0, geodesic=False): points = [] angle_stride = 360 * phi if geodesic else 2 * pi / phi ** 2 b = round(alpha * sqrt(n)) # number of boundary points for k in range(1, n + 1): r = radius(k, n, b) theta = k * angle_stride points.append((r * cos(theta), r * sin(theta))) return points def radius(k, n, b): if k > n - b: return 1.0 else: return sqrt(k - 0.5) / sqrt(n - (b + 1) / 2) # example if __name__ == '__main__': import matplotlib.pyplot as plt fig, ax = plt.subplots() points = sunflower(500, alpha=2, geodesic=False) xs = [point[0] for point in points] ys = [point[1] for point in points] ax.scatter(xs, ys) ax.set_aspect('equal') # display as square plot with equal axes plt.show()

以示例(处理)添加我的Java实现了以前的答案。

import numpy as np import matplotlib.pyplot as plt def sunflower(n: int, alpha: float) -> np.ndarray: # Number of points respectively on the boundary and inside the cirlce. n_exterior = np.round(alpha * np.sqrt(n)).astype(int) n_interior = n - n_exterior # Ensure there are still some points in the inside... if n_interior < 1: raise RuntimeError(f"Parameter 'alpha' is too large ({alpha}), all " f"points would end-up on the boundary.") # Generate the angles. The factor k_theta corresponds to 2*pi/phi^2. k_theta = np.pi * (3 - np.sqrt(5)) angles = np.linspace(k_theta, k_theta * n, n) # Generate the radii. r_interior = np.sqrt(np.linspace(0, 1, n_interior)) r_exterior = np.ones((n_exterior,)) r = np.concatenate((r_interior, r_exterior)) # Return Cartesian coordinates from polar ones. return r * np.stack((np.cos(angles), np.sin(angles))) # NOTE: say the returned array is called s. The layout is such that s[0,:] # contains X values and s[1,:] contains Y values. Change the above to # return r.reshape(n, 1) * np.stack((np.cos(angles), np.sin(angles)), axis=1) # if you want s[:,0] and s[:,1] to contain X and Y values instead. if __name__ == '__main__': fig, ax = plt.subplots() # Let's plot three sunflowers with different values of alpha! for alpha in (0, 1, 2): s = sunflower(500, alpha) # NOTE: the 'alpha=0.5' parameter is to control transparency, it does # not have anything to do with the alpha used in 'sunflower' ;) ax.scatter(s[0], s[1], alpha=0.5, label=f"alpha={alpha}") # Display as square plot with equal axes and add a legend. Then show the result :) ax.set_aspect('equal') ax.legend() plt.show() sunflower-picture

这里是我的团结实施。

1
投票

这是OpenScad版本,借助用户3717023的答案:

int n = 2000; // count of nodes Float alpha = 2.; // constant that can be adjusted to vary the geometry of points at the boundary ArrayList<PVector> vertices = new ArrayList<PVector>(); Float scaleFactor = 200.; // scale points beyond their 0.0-1.0 range for visualisation; void setup() { size(500, 500); // Test vertices = sunflower(n, alpha); displayTest(vertices, scaleFactor); } ArrayList<PVector> sunflower(int n, Float alpha) { Double phi = (1 + Math.sqrt(5)) / 2; // golden ratio Double angle = 2 * PI / Math.pow(phi, 2); // value used to calculate theta for each point ArrayList<PVector> points = new ArrayList<PVector>(); Long b = Math.round(alpha*Math.sqrt(n)); // number of boundary points Float theta, r, x, y; for (int i = 1; i < n + 1; i++) { r = radius(i, n, b.floatValue()); theta = i * angle.floatValue(); x = r * cos(theta); y = r * sin(theta); PVector p = new PVector(x, y); points.add(p); } return points; } Float radius(int k, int n, Float b) { if (k > n - b) { return 1.0; } else { Double r = Math.sqrt(k - 0.5) / Math.sqrt(n - (b+1) / 2); return r.floatValue(); } } void displayTest(ArrayList<PVector> points, Float size) { for (int i = 0; i < points.size(); i++) { Float x = size * points.get(i).x; Float y = size * points.get(i).y; pushMatrix(); translate(width / 2, height / 2); ellipse(x, y, 5, 5); popMatrix(); } }

1
投票

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