Skip to content

Instantly share code, notes, and snippets.

@redraiment
Last active November 14, 2021 15:04
Show Gist options
  • Save redraiment/6962449 to your computer and use it in GitHub Desktop.
Save redraiment/6962449 to your computer and use it in GitHub Desktop.
将n个点均匀地分布在球面上。算法利用正多面体(此处选用正八面体)剖分球面。
// 球面坐标系统
var Spherical = function(radial, polar, azimuthal) {
var self = this;
self.radial = radial || 1
self.polar = polar || 0
self.azimuthal = azimuthal || 0
};
// 转换成直角坐标系统
Spherical.prototype.toCartesian = function() {
var self = this;
var r = Math.sin(self.azimuthal) * self.radial
var x = Math.cos(self.polar) * r
var y = Math.sin(self.polar) * r
var z = Math.cos(self.azimuthal) * self.radial
return [x, y, z]
};
// limit: 要在球面上安置的点的个数
var Splot = function(limit) {
var self = this;
self.s = new Spherical();
self.level = Math.ceil(Math.sqrt((limit - 2) / 4));
self.azimuthal = 0.5 * Math.PI / self.level;
self.a = - self.level;
self.i = 0;
};
// 当前切面分成n个扇区
Splot.prototype.sectionSize = function() {
var self = this;
var size = self.level - Math.abs(self.a);
if (size == 0) {
size = 1;
} else {
size *= 4;
}
return size;
};
Splot.prototype.hasNext = function() {
var self = this;
return self.a <= self.level;
};
// 返回下一个
Splot.prototype.next = function() {
var self = this;
var size = self.sectionSize();
self.i++;
self.s.polar += 2 * Math.PI / size;
var coord = self.s.toCartesian();
if (self.i >= size) {
self.i = 0;
self.a++;
self.s.azimuthal += self.azimuthal;
self.s.polar = 0;
}
return coord;
};
var splot = new Splot(10000);
while (splot.hasNext()) {
splot.next();
}
#!/usr/bin/python
# -*- coding: utf-8 -*-
import math
class Spherical(object):
'''球坐标系'''
def __init__(self, radial = 1.0, polar = 0.0, azimuthal = 0.0):
self.radial = radial
self.polar = polar
self.azimuthal = azimuthal
def toCartesian(self):
'''转直角坐标系'''
r = math.sin(self.azimuthal) * self.radial
x = math.cos(self.polar) * r
y = math.sin(self.polar) * r
z = math.cos(self.azimuthal) * self.radial
return x, y, z
def splot(limit):
s = Spherical()
n = int(math.ceil(math.sqrt((limit - 2) / 4)))
azimuthal = 0.5 * math.pi / n
for a in range(-n, n + 1):
s.polar = 0
size = (n - abs(a)) * 4 or 1
polar = 2 * math.pi / size
for i in range(size):
yield s.toCartesian()
s.polar += polar
s.azimuthal += azimuthal
for point in splot(input('')):
print("%f %f %f" % point)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment