如何从点旋转图形(希尔伯特曲线)?

时间:2016-10-17 10:12:12

标签: c# algorithm graphics fractals

我正在研究希尔伯特曲线,我不能旋转整个图形,只是下方的矩形(看截图,第三步和后续步骤我有问题)

first 3 steps

我有一个Figure类。我用它来存储每一个图形,并从前一个构建下一个文件。这是我的代码

public class Fragment
{
    public static int PADDING = 50;
    public static float sideLength;

    private readonly Pen crimsonPen = new Pen(Color.Crimson);


    public List<PointF> pointsF = new List<PointF>();
    public PointF[] points;

    public Fragment(int step, Graphics graphics)
    {
        sideLength = Form1.sideLenght;
        points = new PointF[(int)Math.Pow(4, step + 1)];

        if (step.Equals(0))
        {
            points[0] = new PointF(PADDING, PADDING + sideLength);
            points[1] = new PointF(PADDING, PADDING);
            points[2] = new PointF(PADDING + sideLength, PADDING);
            points[3] = new PointF(PADDING + sideLength, PADDING + sideLength);
            graphics.DrawLines(crimsonPen, new[] { points[0], points[1], points[2], points[3] });
        }
        else
        {
            var frag = Form1.fragments[step - 1];
            for (var i = 0; i < step; i++)
            {
                PointF tmpPoint;
                // left lower #1 
                for (int j = frag.points.Length - 1; j >= 0; j--)
                {
                    points[frag.points.Length - 1 - j] = frag.points[j];
                    points[frag.points.Length - 1 - j].Y += sideLength * 2 * (i + 1);
                }

                //rotate left lower #1 
                for (int b = 0; b < Math.Pow(4, step) - 1; b++)
                {
                    tmpPoint = points[0];
                    for (int j = 0; j < frag.points.Length; j++)
                    {
                        if (j.Equals(frag.points.Length - 1))
                        {
                            points[j] = tmpPoint;
                        }
                        else
                        {
                            points[j] = points[j + 1];
                        }
                    }
                }

                // left upper #2
                for (int j = 0; j < frag.points.Length; j++)
                {
                    points[j + frag.points.Length] = frag.points[j];
                }

                // right upper #3
                for (int j = 0; j < frag.points.Length; j++)
                {
                    points[j + 2 * frag.points.Length] = points[j + frag.points.Length];
                    points[j + 2 * frag.points.Length].X += sideLength * 2 * (i + 1);
                }

                //right lower #4
                for (int j = frag.points.Length - 1; j >= 0; j--)
                {
                    points[3 * frag.points.Length + j] = points[2 * frag.points.Length + frag.points.Length - j - 1];
                    points[3 * frag.points.Length + j].Y += sideLength * 2 * (i + 1);
                }
                tmpPoint = points[3 * frag.points.Length];
                //rotate right lower #4
                for (int j = 0; j < frag.points.Length; j++)
                {
                    if (j.Equals(frag.points.Length - 1))
                    {
                        points[4 * (frag.points.Length) - 1] = tmpPoint;
                    }
                    else
                    {
                        points[3 * frag.points.Length + j] = points[3 * frag.points.Length + j + 1];
                    }
                }
            }

            graphics.DrawLines(crimsonPen, points);
        }
    }
}

这里我使用递归方法绘制数字

private void drawButton_Click(object sender, EventArgs e)
    {
        canvas.Refresh();
        count = 0;
        if (Int32.TryParse(stepsTextBox.Text, out steps))
        {
            sideLenght = (float)((canvas.Width - 100) / (Math.Pow(2, steps) - 1)); 
            fragments = new Fragment[steps];
            drawCurve();
        }
        else
        {
            MessageBox.Show("Wow, incorrect input", "Try again");
        }
    }

    private void drawCurve()
    {
        if (count < steps)
        {
            fragments[count] = new Fragment(count, graphics);
            ++count;
            drawCurve();
        } 
    }

我试图围绕图中心旋转点并使用下一个代码,但旋转不正确

public PointF rotatePoint(PointF pointToRotate)
    {
        pointToRotate.X = (float)(Math.Cos(180 * Math.PI / 180) * (pointToRotate.X - centerPoint.X) -
                                               Math.Sin(180 * Math.PI / 180) * (pointToRotate.Y - centerPoint.Y) +
                                               centerPoint.X);
        pointToRotate.Y = (float)(Math.Sin(0 * Math.PI / 180) * (pointToRotate.X - centerPoint.X) +
                                               Math.Cos(0 * Math.PI / 180) * (pointToRotate.Y - centerPoint.Y) +
                                               centerPoint.Y);
        return pointToRotate;
    }       

1 个答案:

答案 0 :(得分:1)

问题是您在计算旋转的Y坐标时使用已经旋转的X坐标。使用临时变量来避免这种情况:

public PointF rotatePoint(PointF pointToRotate)
{
    float rotatedX = (float)(Math.Cos(180 * Math.PI / 180) * (pointToRotate.X - centerPoint.X) -
                                           Math.Sin(180 * Math.PI / 180) * (pointToRotate.Y - centerPoint.Y) +
                                           centerPoint.X);
    pointToRotate.Y = (float)(Math.Sin(0 * Math.PI / 180) * (pointToRotate.X - centerPoint.X) +
                                           Math.Cos(0 * Math.PI / 180) * (pointToRotate.Y - centerPoint.Y) +
                                           centerPoint.Y);
    pointToRotate.X = rotatedX;
    return pointToRotate;
}