仅使用线函数绘制科赫曲线
Drawing koch curves only using line function
我正在尝试使用基本的三角转换绘制科赫曲线(线)。
我不知道新生成的峰值点的正确角度是多少。
这是我的逻辑:
给定线的起点、线的角度和每段的长度,创建此方案。
创建好方案后,将每条子线的起点作为新的科赫曲线,重复上述步骤
我怀疑问题出在点 '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 调用此函数我得到:
我想要这样的东西:
据我所知基本的科赫曲线是从一条直线开始,将step的长度一分为三,中间放一个等边三角形:
如果您感兴趣,可以使用不同的变体,但对于基本的科赫曲线,您可以从绘制的 p1, p2, p3, pt and start
个点中的任意两个点开始,然后分别计算其余点。在每次迭代中,您可以更深入一层。
我不愿意回答,因为我没有在 Unity 中编码,但几天后你的问题仍然没有任何有效答案,这里是我的:
我没有在 turtle 图形代码中看到我期望的内容。参见:
并在代码中查找 turtle_draw
。这就是我所期望的:
初始字符串
海龟分形由包含海龟命令的字符串表示。通常的命令是:
f
按预定步骤前进
l
在你的情况下按预定角度左转 (CCW) 60 deg
r
按您的情况按预定角度右转 (CW) 60 deg
对于科赫雪花,你应该从三角形开始,所以 "frrfrrf"
科赫曲线从单线开始 "f"
。
iteration/recursion
对于分形的每个 iteration/recursion 级别,您应该将每个直线命令 f
替换为三角形凹凸特征 "flfrrflf"
(确保最后一个方向与原始 f
命令)。由于三角形的大小增加了三倍,您应该将 f
运动的大小除以 3
以保持相同的比例 ...
渲染字符串
简单地处理结果字符串的所有字符并渲染这些行。有两种方法可以处理旋转。要么记住方向角并通过旋转角度 inc/dec
并计算线作为极坐标增量(参见下面的代码),要么以 2D(或更高维度)向量的形式具有方向并在其上应用旋转公式(见上面的link)。
这里是科赫雪花的小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 东西。这里重要的是:
void turtle(TCanvas *scr,float x,float y,float a,float dl,AnsiString s)
在 canvas scr
上呈现字符串 s
(使用 VCL 封装的 GDI),其中 x,y
是起始位置 a
是起始方向角 [rad]
和 dl
是行的大小。
AnsiString replace(AnsiString s0,char find,AnsiString replace)
用作为新字符串返回的 replace
模式替换 s0
中的任何 find
字符。
void draw()
计算和渲染分形
这里有几张截图:
现在,当我查看您的代码时(只是快速浏览一下,因为我懒得深入分析您的代码),您正在直接生成点,而无需增量步骤。相反,您有点像 hard-coding 三角形凹凸特征,如果没有巧妙的索引技术,该特征将无法在下一级分形递归中正常工作。在您的情况下,即使在相同级别的递归中它也会停止正常工作(在下一行,因为它的方向不同并且您没有旋转而是 hard-coding 功能)。
我正在尝试使用基本的三角转换绘制科赫曲线(线)。
我不知道新生成的峰值点的正确角度是多少。
这是我的逻辑:
给定线的起点、线的角度和每段的长度,创建此方案。
创建好方案后,将每条子线的起点作为新的科赫曲线,重复上述步骤
我怀疑问题出在点 '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 调用此函数我得到:
我想要这样的东西:
据我所知基本的科赫曲线是从一条直线开始,将step的长度一分为三,中间放一个等边三角形:
如果您感兴趣,可以使用不同的变体,但对于基本的科赫曲线,您可以从绘制的 p1, p2, p3, pt and start
个点中的任意两个点开始,然后分别计算其余点。在每次迭代中,您可以更深入一层。
我不愿意回答,因为我没有在 Unity 中编码,但几天后你的问题仍然没有任何有效答案,这里是我的:
我没有在 turtle 图形代码中看到我期望的内容。参见:
并在代码中查找 turtle_draw
。这就是我所期望的:
初始字符串
海龟分形由包含海龟命令的字符串表示。通常的命令是:
f
按预定步骤前进l
在你的情况下按预定角度左转 (CCW)60 deg
r
按您的情况按预定角度右转 (CW)60 deg
对于科赫雪花,你应该从三角形开始,所以
"frrfrrf"
科赫曲线从单线开始"f"
。iteration/recursion
对于分形的每个 iteration/recursion 级别,您应该将每个直线命令
f
替换为三角形凹凸特征"flfrrflf"
(确保最后一个方向与原始f
命令)。由于三角形的大小增加了三倍,您应该将f
运动的大小除以3
以保持相同的比例 ...渲染字符串
简单地处理结果字符串的所有字符并渲染这些行。有两种方法可以处理旋转。要么记住方向角并通过旋转角度
inc/dec
并计算线作为极坐标增量(参见下面的代码),要么以 2D(或更高维度)向量的形式具有方向并在其上应用旋转公式(见上面的link)。
这里是科赫雪花的小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 东西。这里重要的是:
void turtle(TCanvas *scr,float x,float y,float a,float dl,AnsiString s)
在 canvas
scr
上呈现字符串s
(使用 VCL 封装的 GDI),其中x,y
是起始位置a
是起始方向角[rad]
和dl
是行的大小。AnsiString replace(AnsiString s0,char find,AnsiString replace)
用作为新字符串返回的
replace
模式替换s0
中的任何find
字符。void draw()
计算和渲染分形
这里有几张截图:
现在,当我查看您的代码时(只是快速浏览一下,因为我懒得深入分析您的代码),您正在直接生成点,而无需增量步骤。相反,您有点像 hard-coding 三角形凹凸特征,如果没有巧妙的索引技术,该特征将无法在下一级分形递归中正常工作。在您的情况下,即使在相同级别的递归中它也会停止正常工作(在下一行,因为它的方向不同并且您没有旋转而是 hard-coding 功能)。