【问题标题】:Drawing koch curves only using line function仅使用线函数绘制科赫曲线
【发布时间】:2019-05-22 20:49:37
【问题描述】:

我正在尝试用基本的三角转换绘制科赫曲线(线)。

我不知道新生成的峰值点的正确角度是多少。

这是我的逻辑:

给定线的起点、线的角度和每段的长度,创建此方案。

创建方案后,将每条子线起点作为新的科赫曲线,重复上述步骤。

我怀疑问题出在点'pt'角度值。

/* Angle for turning downwards after the peak point */
float angle = 2*PI - PI/6;

void koch(Point2D start, float alpha, int d, int noi) {

  Point2D p1 = new Point2D(start.x + d*cos(alpha), start.y + d*sin(alpha));
  Point2D pt = new Point2D(start.x + d*sqrt(3)*cos(alpha+PI/6), start.y + d*sqrt(3)*sin(alpha+PI/6));
  Point2D p2 = new Point2D(start.x + 2*d*cos(alpha), start.y + 2*d*sin(alpha));
  Point2D p3 = new Point2D(start.x + 3*d*cos(alpha), start.y + 3*d*sin(alpha));

  line(start.x, start.y, p1.x, p1.y);
  line(p1.x, p1.y, pt.x, pt.y);
  line(pt.x, pt.y, p2.x, p2.y);            
  line(p2.x, p2.y, p3.x, p3.y);

  if(noi != 0) {
    koch(start, alpha, d/3, noi-1);

    koch(p1, alpha + PI/3, d/3, noi-1);

    koch(pt, angle, d/3, noi-1);         //Problem is here i suspect

    koch(p2, alpha, d/3, noi-1);

  } 

  return;

}

使用 alpha 为 PI/6 且 noi 为 2 调用此函数我得到:

我想得到类似的东西:

【问题讨论】:

  • 那么,问题点处pt 的值多少?一些简单的print 命令将显示这些值并跟踪它们的派生。请参阅这个可爱的 debug 博客寻求帮助。
  • 由于缺乏任何有效答案,我将评论转换为答案。 (希望有团结背景的人会回答)

标签: algorithm recursion drawing processing fractals


【解决方案1】:

我不愿意回答,因为我没有在 Unity 中编码,但是几天后您的问题仍然没有任何有效的答案,这是我的:

我没有看到我对海龟图形代码的期望。见:

并在代码中查找turtle_draw。这是我所期望的:

  1. 初始字符串

    海龟分形由一个包含海龟命令的字符串表示。通常的命令是:

    • f按预定步骤前进
    • l 在您的情况下以预定角度左转 (CCW) 60 deg
    • r 在您的情况下以预定角度右转 (CW) 60 deg

    对于 Koch 雪花,您应该从三角形开始,因此 "frrfrrf" Koch 曲线以单线 "f" 开始。

  2. 迭代/递归

    对于分形的每个迭代/递归级别,您应该将每个直线命令f 替换为三角形凹凸特征"flfrrflf"(确保最后一个方向与原始f 命令匹配)。随着三角形的大小增加三倍,您应该将f 运动的大小除以3 以保持相同的比例......

  3. 渲染字符串

    只需处理结果字符串的所有字符并渲染行。有两种方法可以处理旋转。要么通过旋转角度记住方向角和inc/dec,然后将线计算为极坐标增量(参见下面的代码),或者以二维(或更高维度)向量的形式具有方向并在其上应用旋转公式(参见上面的链接)。

这里是科赫雪花的小C++/VCL示例:

//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop

#include "win_main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
Graphics::TBitmap *bmp=new Graphics::TBitmap;
int xs,xs2,ys,ys2,n=0;
AnsiString str;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void turtle(TCanvas *scr,float x,float y,float a,float dl,AnsiString s)
    {
    int i;
    char c;
    float da=60.0*M_PI/180.0;
    scr->MoveTo(x,y);
    for (i=1;i<=s.Length();i++)
        {
        c=s[i];
        if (c=='f')
            {
            x+=dl*cos(a);
            y+=dl*sin(a);
            scr->LineTo(x,y);
            }
        if (c=='l') a-=da;
        if (c=='r') a+=da;
        }
    }
//---------------------------------------------------------------------------
AnsiString replace(AnsiString s0,char find,AnsiString replace)
    {
    int i;
    char c;
    AnsiString s="";
    for (i=1;i<=s0.Length();i++)
        {
        c=s0[i];
        if (c==find) s+=replace;
        else s+=c;
        }
    return s;
    }
//---------------------------------------------------------------------------
void draw()
    {
    str="frrfrrf"; // initial string
    for (int i=0;i<n;i++) str=replace(str,'f',"flfrrflf"); // n times replacement

    bmp->Canvas->Brush->Color=0x00000000; // just clear screen ...
    bmp->Canvas->FillRect(TRect(0,0,xs,ys));
    bmp->Canvas->Pen  ->Color=0x00FFFFFF; // and some info text
    bmp->Canvas->Font ->Color=0x00FFFFFF;
    bmp->Canvas->TextOutA(5,5,AnsiString().sprintf("n:%i",n));
    float nn=pow(3,n),a;
    a=xs; if (a>ys) a=ys; a=0.75*a/nn;

    turtle(bmp->Canvas,xs2-(0.5*nn*a),ys2-(0.33*nn*a),0.0,a,str); // render fractal
    Form1->Canvas->Draw(0,0,bmp); // swap buffers to avoid flickering
    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
    {
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
    delete bmp;
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
    {
    bmp->Width=ClientWidth;
    bmp->Height=ClientHeight;
    xs=ClientWidth;
    ys=ClientHeight;
    xs2=xs>>1;
    ys2=ys>>1;
    draw();
    }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    draw();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
    {
    if (WheelDelta<0) if (n<8) n++;
    if (WheelDelta>0) if (n>0) n--;
    Handled=true;
    draw();
    }
//---------------------------------------------------------------------------

忽略 VCL 的东西。这里重要的是:

  1. void turtle(TCanvas *scr,float x,float y,float a,float dl,AnsiString s)

    在画布scr(使用VCL封装的GDI)上呈现字符串s,其中x,y是起始位置a是起始方向角度[rad]dl是线的大小。

  2. AnsiString replace(AnsiString s0,char find,AnsiString replace)

    s0 中的任何find 字符替换为replace 模式,作为新字符串返回。

  3. void draw()

    计算和渲染分形

这里有几张截图:

现在,当我查看您的代码时(只是快速浏览一下,因为我懒得深入分析您的代码),您正在直接生成点,而不需要增量步骤。相反,如果没有巧妙的索引技术,您将在某种程度上对三角形凹凸特征进行硬编码,该特征将无法在下一级分形递归中正常工作。在您的情况下,即使在相同级别的递归中它也停止正常工作(在下一行,因为它的方向不同,您不是旋转而是硬编码该功能)。

【讨论】:

    【解决方案2】:

    据我所知,基本的科赫曲线从一条线开始,将步长分成三份,中间放一个等边三角形:

    如果您有兴趣,那里有不同的变化,但对于基本的科赫曲线,您可以从您绘制的 p1, p2, p3, pt and start 点中的任意两个开始,然后分别计算其余部分。在每次迭代中,您可以更深一层。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      • 2015-02-22
      • 2017-09-03
      • 1970-01-01
      相关资源
      最近更新 更多