9

Vector我正在尝试生成一组大致模拟螺旋星系的点(由结构表示)。

我一直在玩的 C# 代码如下;但我似乎只能让它生成银河系的一个“手臂”。

    public Vector3[] GenerateArm(int numOfStars, int numOfArms, float rotation)
    {
        Vector3[] result = new Vector3[numOfStars];
        Random r = new Random();

        float fArmAngle = (float)((360 / numOfArms) % 360);
        float fAngularSpread = 180 / (numOfArms * 2);

        for (int i = 0; i < numOfStars; i++)
        {

            float fR = (float)r.NextDouble() * 64.0f;
            float fQ = ((float)r.NextDouble() * fAngularSpread) * 1;
            float fK = 1;

            float fA = ((float)r.NextDouble() % numOfArms) * fArmAngle;


            float fX = fR * (float)Math.Cos((MathHelper.DegreesToRadians(fA + fR * fK + fQ)));
            float fY = fR * (float)Math.Sin((MathHelper.DegreesToRadians(fA + fR * fK + fQ)));

            float resultX = (float)(fX * Math.Cos(rotation) - fY * Math.Sin(rotation));
            float resultY = (float)(fY * Math.Cos(rotation) - fX * Math.Sin(rotation));

            result[i] = new Vector3(resultX, resultY, 1.0f);
        }

        return result;
    }
4

3 回答 3

5

检查这个。这是使用密度波理论对星系的模拟。代码可用。 http://beltoforion.de/galaxy/galaxy_en.html

于 2012-07-11T14:49:57.830 回答
5

我非常喜欢这个想法,我不得不自己玩弄它,这就是我的结果。请注意,我使用的是 PointF 而不是 Vector3,但您应该能够, 0)在几个地方进行搜索、替换和添加。

PointF[] points;

private void Render(Graphics g, int width, int height)
{
    using (Brush brush = new SolidBrush(Color.FromArgb(20, 150, 200, 255)))
    {
        g.Clear(Color.Black);
        foreach (PointF point in points)
        {
            Point screenPoint = new Point((int)(point.X * (float)width), (int)(point.Y * (float)height));
            screenPoint.Offset(new Point(-2, -2));
            g.FillRectangle(brush, new Rectangle(screenPoint, new Size(4, 4)));
        }
        g.Flush();
    }
}

public PointF[] GenerateGalaxy(int numOfStars, int numOfArms, float spin, double armSpread, double starsAtCenterRatio)
{
    List<PointF> result = new List<PointF>(numOfStars);
    for (int i = 0; i < numOfArms; i++)
    {
        result.AddRange(GenerateArm(numOfStars / numOfArms, (float)i / (float)numOfArms, spin, armSpread, starsAtCenterRatio));
    }
    return result.ToArray();
}

public PointF[] GenerateArm(int numOfStars, float rotation, float spin, double armSpread, double starsAtCenterRatio)
{
    PointF[] result = new PointF[numOfStars];
    Random r = new Random();

    for (int i = 0; i < numOfStars; i++)
    {
        double part = (double)i / (double)numOfStars;
        part = Math.Pow(part, starsAtCenterRatio);

        float distanceFromCenter = (float)part;
        double position = (part * spin + rotation) * Math.PI * 2;

        double xFluctuation = (Pow3Constrained(r.NextDouble()) - Pow3Constrained(r.NextDouble())) * armSpread;
        double yFluctuation = (Pow3Constrained(r.NextDouble()) - Pow3Constrained(r.NextDouble())) * armSpread;

        float resultX = (float)Math.Cos(position) * distanceFromCenter / 2 + 0.5f + (float)xFluctuation;
        float resultY = (float)Math.Sin(position) * distanceFromCenter / 2 + 0.5f + (float)yFluctuation;

        result[i] = new PointF(resultX, resultY);
    }

    return result;
}

public static double Pow3Constrained(double x)
{
    double value = Math.Pow(x - 0.5, 3) * 4 + 0.5d;
    return Math.Max(Math.Min(1, value), 0);
}

例子:

points = GenerateGalaxy(80000, 2, 3f, 0.1d, 3);

结果: 星系

于 2014-12-29T21:20:01.353 回答
2

我会将该函数抽象为一个createArm函数。

然后,您可以(暂时)将每条手臂存储为自己的星系。

所以如果你想要 2 个手臂,做 2 个 5000 的星系。然后,将其中一个围绕原点旋转 0 度(所以不要移动),另一个围绕原点旋转 180 度。

有了这个,你可以通过使用不同的旋转量来做任意数量的手臂。您甚至可以通过使旋转距离更加随机来为其添加一些“自然化”,例如使用范围而不是直线 (360 / n)。例如,5 个手臂将是 0、72、144、216、288。但是通过一些随机化,您可以使其成为 0、70、146、225、301。

编辑:

一些快速的 google-fu 告诉我(来源

q = initial angle, f  = angle of rotation.

x = r cos q
y = r sin q

x' = r cos ( q + f ) = r cos q cos f - r sin q sin f
y' = r sin ( q + w ) = r sin q cos f + r cos q sin f

hence:
x' = x cos f - y sin f
y' = y cos f + x sin f 
于 2011-09-06T17:44:06.853 回答