Рисование кривых Коха только с помощью функции линии - PullRequest
1 голос
/ 22 мая 2019

Я пытаюсь нарисовать кривую Коха (линию) с основными тригонометрическими преобразованиями.

Я не мог понять, какой правильный угол для вновь созданной точки пика.

Вот моя логика: Points

С учетом начальной точки линии, угла наклона линии и длины каждого сегмента создайте эту схему.

После создания схемы обработайте каждую отправную точку подстрок как новые кривые Коха и повторите шаги.

Я подозреваю, что проблема в значении угла '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;

}

Вызов этой функции с альфа, равным PI / 6, а noi равен 2, я получаю: This

Я хочу получить что-то вроде: This

Ответы [ 2 ]

2 голосов
/ 25 мая 2019

Я не хотел отвечать, поскольку я не кодирую в Unity , но, поскольку ваш вопрос через несколько дней все еще не дал никакого действительного ответа, мой:

Я не вижу, чего бы я ожидал в графическом коде черепахи. См:

и найдите turtle_draw в коде. Это то, что я ожидал:

  1. начальная строка

    черепахи фракталы представлены строкой, содержащей команды черепахи. Обычные команды:

    • f перейти на заданный шаг
    • l поверните налево (против часовой стрелки) на заданный угол в вашем случае 60 deg
    • r поверните направо (CW) на заданный угол в вашем случае 60 deg

    Для снежинки Коха вы должны начать с треугольника, поэтому "frrfrrf" Кривая Коха начинается с одной линии "f".

  2. итерация / рекурсии

    для каждого уровня итерации / рекурсии фрактала вы должны заменить каждую команду прямой линии f на треугольную функцию "flfrrflf" (убедитесь, что последнее направление соответствует исходной команде f). Поскольку размер треугольника утроился, вы должны разделить размер движения f на 3, чтобы остаться в том же масштабе ...

  3. рендеринг строки

    просто обрабатывает все символы полученной строки и отображает строки. Есть два подхода к обработке поворотов. Либо запомните угол направления и inc/dec его по углу поворота и вычислите линии с приращением полярных координат (см. Код ниже), либо укажите направление в виде вектора 2D (или большего размера) и примените к нему формулу вращения (см. ссылка выше).

Здесь маленький 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)

    , который отображает строку s на холсте scr (с использованием инкапсулированного GDI VCL), где x,y - начальная позиция a - начальный угол направления [rad], а dl - размер линии.

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

    , которые заменяют любые символы find в шаблоне s0 на replace, возвращаемые в виде новой строки.

  3. void draw()

    , который вычисляет и отображает фрактал

Вот несколько скриншотов:

n=0 n=1 n=2 n=3

Теперь, когда я смотрю на ваш код (просто бегло, потому что мне лень глубоко анализировать ваш код), вы генерируете точки напрямую, без необходимости дополнительных шагов. Вместо этого вы как бы жестко программируете функцию треугольной выпуклости, которая не будет работать должным образом для следующего уровня фрактальной рекурсии без умных методов индексации. В вашем случае он перестает работать должным образом даже на том же уровне рекурсии (на следующей строке, потому что он ориентирован по-другому, и вы не вращаетесь, а жестко программируете функцию).

1 голос
/ 23 мая 2019

Насколько я знаю, базовая кривая Коха начинается с линии, делит длину шага на три и помещает равносторонний треугольник в середину:

enter image description here

Существуют различные варианты, если вас интересует, но для базовой кривой Коха вы можете начать с двух из p1, p2, p3, pt and start точек, которые вы нарисовали, и рассчитать остальные соответственно. В каждой итерации вы можете идти на один уровень глубже.

...