为什么我的龙分形不完整

时间:2011-10-09 10:44:27

标签: c# javascript fractals

我已将代码从javascript翻译成c#,可以通过http://fractal.qfox.nl/dragon.js

上的优秀演示找到

我的翻译是为了在点击按钮时只产生一条龙,但我想我的版本中遗漏了一些东西 有关详细信息,请参阅维基百科文章:Dragon Curve

不完整的龙分形输出: sickly dragon代码:

public partial class MainPage : UserControl
{
    PointCollection pc;

    Int32[] pattern = new Int32[] { 1, 1, 0, 2, 1, 0, 0, 3 };
    Int32[] position = new Int32[] { 0, 0, 0, 0, 0, 0, 0, 0 };
    Boolean toggle;
    Char r = default(Char);

    Int32 distance = 10; // line length
    Int32 step = 100; // paints per step
    Int32 skip = 10; // folds per paint

    Double x = 0;
    Double y = 0;
    Int32 a = 90;


    public MainPage()
    {
        InitializeComponent();
    }


    private void btnFire_Click(object sender, RoutedEventArgs e)
    {

        x = canvas.ActualWidth / 3;
        y = canvas.ActualHeight / 1.5;

        pc = new PointCollection();

        var n = step;
        while (--n > 0)
        {
            List<Char> s = getS(skip);
            draw(s);
        }

        Polyline p = new Polyline();
        p.Stroke = new SolidColorBrush(Colors.Red);
        p.StrokeThickness = 0.5;

        p.Points = pc;
        canvas.Children.Add(p);
    }


    List<Char> getS(Int32 n)
    {
        List<Char> s1 = new List<Char>();
        while (n-- > 0) s1.Add(getNext(0));
        return s1;
    }


    void draw(List<Char> s)
    {        
        pc.Add(new Point(x, y));
        for (Int32 i = 0, n = s.Count; i < n; i++)
        {
            pc.Add(new Point(x, y));
            Int32 j;
            if (int.TryParse(s[i].ToString(), out j) && j != 0)
            {
                if ((a + 90) % 360 != 0)
                {
                    a = (a + 90) % 360;
                }
                else
                {
                    a = 360; // Right
                }
            }
            else
            {
                if (a - 90 != 0)
                {
                    a = a - 90;
                }
                else
                {
                    a = 360; // Right
                }
            }
            // new target
            if (a == 0 || a == 360)
            {
                y -= distance;
            }
            else if (a == 90)
            {
                x += distance;
            }
            else if (a == 180)
            {
                y += distance;
            }
            else if (a == 270)
            {
                x -= distance;
            }

            // move
            pc.Add(new Point(x, y));
        }

    }

    Char getNext(Int32 n)
    {
        if (position[n] == 7)
        {
            r = getNext(n + 1);
            position[n] = 0;
        }
        else
        {
            var x = position[n] > 0 ? pattern[position[n]] : pattern[0];

            switch (x)
            {
                case 0:
                    r = '0';
                    break;
                case 1:
                    r = '1';
                    break;
                case 2:
                    if (!toggle)
                    {
                        r = '1';
                    }
                    else
                    {
                        r = '0';
                    }
                    toggle = !toggle;
                    break;
            }
            position[n] = position[n] + 1;                
        }

        return r;
    }

}

1 个答案:

答案 0 :(得分:4)

我清理了代码,并尝试了解patternposition数组应该如何生成正确的序列,但我无法弄明白。 pattern数组中的最后一项例如从未使用过......

然而,有一种更简单的方法只使用计数器实现getNext方法:

bool getNext() {
  cnt++;
  return (cnt & ((cnt & -cnt) << 1)) != 0;
}

我之前(约20年前)使用过该方法,我在dragon curve wikipedia page上找到了这个实现。

使用此getNext实现的已清理代码如下所示:

public partial class MainPage : UserControl {
    PointCollection pc;

    int cnt = 0;

    int distance = 10; // line length
    int steps = 1024; // number of paints

    int x = 0;
    int y = 0;
    int a = 90;


    public MainPage() {
        InitializeComponent();
    }


    private void btnFire_Click(object sender, RoutedEventArgs e) {

        x = (int)(canvas.ActualWidth / 3);
        y = (int)(canvas.ActualHeight / 1.5);

        pc = new PointCollection();

        draw(getS(steps));

        Polyline p = new Polyline();
        p.Stroke = new SolidColorBrush(Colors.Red);
        p.StrokeThickness = 0.5;

        p.Points = pc;
        canvas.Children.Add(p);
    }


    List<bool> getS(int n) {
        List<bool> s1 = new List<bool>();
        while (n-- > 0) {
            s1.Add(getNext());
        }
        return s1;
    }


    void draw(List<bool> s) {
        pc.Add(new Point(x, y));
        foreach (bool z in s) {

            a = (a + (z ? 90 : 270)) % 360;

            // new target
            switch (a) {
                case 90: x += distance; break;
                case 180: y += distance; break;
                case 270: x -= distance; break;
                default: y -= distance; break;
            }

            // move
            pc.Add(new Point(x, y));
        }

    }

    bool getNext() {
        cnt++;
        return (cnt & ((cnt & -cnt) << 1)) != 0;
    }

}