Recursion 画出",;“生命的种子”;没有重画任何东西
我有一个稍微有趣的问题,我还不能完全弄清楚(虽然公平地说,我喝得很醉) “”是从半径相等的绘图圆创建的图案,以上一个圆的交点为中心 语言并不重要,理论在这里更重要。任何能画圆圈的东西都可以。例如,HTML5+JSCanvas就可以做到这一点。这是递归如何帮助解决问题的一个很好的例子 问题是,一个天真的方法最终会重新画出很多很多圈。有了7个图层,您将获得超过300000个圆形绘图 一种简单的方法是维护以前的圆中心点列表,并且只绘制不在该列表中的圆 我的问题是,是否有“更好”的方法来解决这个问题?不需要检查列表的东西Recursion 画出",;“生命的种子”;没有重画任何东西,recursion,graphics,Recursion,Graphics,我有一个稍微有趣的问题,我还不能完全弄清楚(虽然公平地说,我喝得很醉) “”是从半径相等的绘图圆创建的图案,以上一个圆的交点为中心 语言并不重要,理论在这里更重要。任何能画圆圈的东西都可以。例如,HTML5+JSCanvas就可以做到这一点。这是递归如何帮助解决问题的一个很好的例子 问题是,一个天真的方法最终会重新画出很多很多圈。有了7个图层,您将获得超过300000个圆形绘图 一种简单的方法是维护以前的圆中心点列表,并且只绘制不在该列表中的圆 我的问题是,是否有“更好”的方法来解决这个问题?不
一个值得思考的有趣问题。多亏了一位朋友,我想我已经解决了这个问题。我将在这里发布我现在正在做的事情,以防有人好奇 简而言之,从中心开始计算六边形的顶点,并将六边形的每条边细分为
i
个位置,其中i
是层编号
我使用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, radius, 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;
}
const float seedAngle=(float)(Math.PI/3.0);
静态无效SeedOfLifeDemo(int x,int y){
//设置Skia工具时,这将根据您使用的语言而有所不同。
var info=新的SKImageInfo(x,y);
使用var bitmap=FlatImage(info,SKColors.White);
SKCanvas canvas=新的SKCanvas(位图);
浮动半径=数学最小值(x,y)/15;
SKPoint中心=新SKPoint(x/2f,y/2f);
SKPaint strokePaint=新SKPaint{
颜色=黑色,
Style=SKPaintStyle.Stroke,
冲程宽度=1,
Isatarias=正确,
};
int层=4;
//画一个非常中心的圆。这比将边的大小写添加到细分的六边形点要简单一点
画布。画圈(中心、半径、笔画);
对于(int i=1;i 0){
浮点xDist=(point.X-prevPoint.Value.X)/细分;
float yDist=(point.Y-prevPoint.Value.Y)/细分;
对于(int sub=1;sub
这确实是一个非常有趣的练习,也是一个例子,说明递归在使用不当时会对您造成伤害。您不能“保存”当前画布并在该图像上绘制新的圆圈吗?您将需要跟踪以前的圆圈位置,但不必每次都重新绘制。是的,您可以,但这不是真正的问题。问题是,如果每个圆圈周围都有六个“孩子”,那么其中至少有一个会与其邻居的孩子重叠。