绘制“生命的种子”而不重绘任何内容

我有一个非常有趣的问题,我无法弄清楚(尽管公平地说,我很醉)

Seed of Life”是一种图案,它是从以上一个圆的交点为中心绘制等半径的圆创建的。

语言并不重要,理论在这里更重要。任何可以画圆的东西都可以做到。例如,HTML5 + JS画布可以做到这一点。这是递归如何帮助解决问题的一个很好的例子。

问题在于,幼稚的方法最终会重画很多圈子。共有7层,您最终将获得超过30万次的圆形绘制。

一种简单的方法是维护先前圆心的列表,并且仅绘制不在该列表中的圆。

我的问题是,是否有一种“更好”的方法来解决这个问题?不需要检查该列表的东西。

一个值得思考的有趣问题。

xiaoyu8848 回答:绘制“生命的种子”而不重绘任何内容

我想我已经解决了这个问题,这要感谢一位朋友。我会在这里发布我现在正在做的事情,以防有人好奇。

简而言之,从中心开始算出六边形的顶点,然后将六边形的每个边细分为i个位置,其中i是层数。 / p>

我使用SkiaSharp用C#绘制了它,但是代码对语言而言并没有什么特别之处,没有理由不能用任何语言编写该代码。这是重要的位:

const float seedAngle = (float)(Math.PI / 3.0);

static void SeedOfLifeDemo(int x,int y) {
    //setting up Skia stuff,this will be different depending what language you're using.
    var info = new SKImageInfo(x,y);
    using var bitmap = FlatImage(info,SKColors.White);

    SKCanvas canvas = new SKCanvas(bitmap);
    float radius = Math.Min(x,y) / 15;

    SKPoint center = new SKPoint(x / 2f,y / 2f);

    SKPaint strokePaint = new SKPaint {
        Color = SKColors.Black,Style = SKPaintStyle.Stroke,StrokeWidth = 1,IsAntialias = true,};

    int layers = 4;
    //Draw the very central circle. This is just a little easier than adding that edge case to SubdividedHexagonAboutPoint
    canvas.DrawCircle(center,radius,strokePaint);
    for (int i = 1; i <= layers; i++) {
        foreach (SKPoint p in SubdividedHexagonAboutPoint(center,radius * i,i)) {
            canvas.DrawCircle(p,strokePaint);
        }
    }
    SaveImage(bitmap,"SeedOfLifeFastDemo.Jpg");//More Skia specific stuff
}

//The magic!
static List<SKPoint> SubdividedHexagonAboutPoint(SKPoint centre,float radius,int subdivisions) {
    List<SKPoint> points = new List<SKPoint>(6 * subdivisions);
    SKPoint? prevPoint = null;
    for (int i = 0; i < 7; i++) {//Step around the circle. The 7th step is to close the last edge
        float x = (float)(Math.Sin(seedAngle * i) * radius + centre.X);
        float y = (float)(Math.Cos(seedAngle * i) * radius + centre.Y);

        SKPoint point = new SKPoint(x,y);
        if (prevPoint != null) {
            points.Add(point);//include the "primary" 6 points
            if (subdivisions > 0) {
                float xDist = (point.X - prevPoint.Value.X) / subdivisions;
                float yDist = (point.Y - prevPoint.Value.Y) / subdivisions;

                for (int sub = 1; sub < subdivisions; sub++) {
                    SKPoint subPoint = new SKPoint(point.X - xDist * sub,point.Y - yDist * sub);
                    points.Add(subPoint);//include the edge subdivisions
                }
            }
        }
        prevPoint = point;
    }
    return points;
}

这确实是一个非常有趣的练习,这是递归使用不当会真正咬住你的另一个例子。

本文链接:https://www.f2er.com/3118118.html

大家都在问