Gosper Fractal lazarus / 39-Graphics ---------------------------------------------------------------------- Boleeman · 2024-05-03 13:27 I have a working version of the Gosper Fractal Curve that uses Lsystem grammar syntax. Was wondering if anyone knows how to make a Gosper Fractal Curve without using Lsystem grammar syntax. I tried converting unsuccessfully from a java version from https://github.com/0razzu/Peano-Gosper-curve. Only level 1 was correct. Not sure if there is anyone knowledgeable of java and how to convert. Anyway I thought I would ask. Cheers. ---------------------------------------------------------------------- Boleeman · 2024-05-04 07:16 Showing the levels of the Gosper Fractal (attached below). Also found a JavaScript that makes the fractal. Might try to convert this to Lazarus. ---------------------------------------------------------------------- Boleeman · 2024-05-05 06:55 I tried converting the JavaScript code (as it scaled the fractal niceley in the javascript version) but I get an error in the private declarations section at the 2nd array of TPointWithAngle; in function kochGenerator(iterTotal: Integer; dotsArray: array of TPointWithAngle): array of TPointWithAngle; If I use function kochGenerator(iterTotal: Integer; dotsArray: array of TPointWithAngle): TPointWithAngle; then the error goes, but I don't have an array of an array of TPointWithAngle. The error message suggests that the compiler is unable to recognize TPointWithAngle as a type identifier, even though it's defined within the interface section. Is the issue related to how it's referenced or used in subsequent function declarations? Here is the converted code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Math, LCLIntf; type  TPointWithAngle = record    point: record      x, y: Double;    end;    angleDegree: Double;  end;   TForm1 = class(TForm)    procedure FormCreate(Sender: TObject);  private    function Map(value, istart, istop, ostart, ostop: Double): Double;    function LerpColor(color1, color2: TColor; t: Double): TColor;    function KochLineEnd(x, y, length, angleDegree: Real): TPointWithAngle;    function LeftRightGosperLine(x, y, newLength, angleDegree: Real): TPointWithAngle;    function ConvertLineToLeftRightKochShape(x1, y1, x2, y2, angleDegree: Real): TPointWithAngle;    //function kochGenerator(iterTotal: Integer; dotsArray: array of TPointWithAngle): TPointWithAngle;    function kochGenerator(iterTotal: Integer; dotsArray: array of TPointWithAngle): array of TPointWithAngle;    procedure setup();    procedure draw();    procedure connectTheDots(dotsArray: array of TPointWithAngle);  public   end; const  scalingFactor = 1/Sqrt(7);  iterTotal = 4;  newLength = 410;  shiftAngle: Double = 0;   x1 = 450; // Adjusted x1 coordinate for the center  y1 = 400; // Adjusted y1 coordinate for the center   color1 = TColor($E9967A);  color2 = clWhite;  strokeColor = clBlue; var  Form1: TForm1;  angleDegree1: Double;  resultDots1: array of TPointWithAngle; implementation {$R *.lfm} function Map(value, istart, istop, ostart, ostop: Double): Double;begin  Result := ostart + (ostop - ostart) * ((value - istart) / (istop - istart));end; function LerpColor(color1, color2: TColor; t: Double): TColor;var  r1, g1, b1, r2, g2, b2: Byte;begin  r1 := GetRValue(color1);  g1 := GetGValue(color1);  b1 := GetBValue(color1);  r2 := GetRValue(color2);  g2 := GetGValue(color2);  b2 := GetBValue(color2);   Result := RGB(    Round(r1 + (r2 - r1) * t),    Round(g1 + (g2 - g1) * t),    Round(b1 + (b2 - b1) * t)  );end; function KochLineEnd(x, y, length, angleDegree: Real): TPointWithAngle;var  newX, newY: Real;begin  newX := x + length * Cos(DegToRad(angleDegree));  newY := y - length * Sin(DegToRad(angleDegree)); // Invert y direction  Result.point.x := newX;  Result.point.y := newY;  Result.angleDegree := angleDegree;end; function LeftRightGosperLine(x, y, newLength, angleDegree: Real): TPointWithAngle;var  p1, p2, p3, p4, p5, p6, p7, p8: TPointWithAngle;begin  p1.point.x := x;  p1.point.y := y;  p1.angleDegree := angleDegree;   p2 := KochLineEnd(p1.point.x, p1.point.y, newLength, p1.angleDegree);  p3 := KochLineEnd(p2.point.x, p2.point.y, newLength, p2.angleDegree + shiftAngle);  p4 := KochLineEnd(p3.point.x, p3.point.y, newLength, p3.angleDegree + 2 * shiftAngle);  p5 := KochLineEnd(p4.point.x, p4.point.y, newLength, p4.angleDegree - shiftAngle);  p6 := KochLineEnd(p5.point.x, p5.point.y, newLength, p5.angleDegree - 2 * shiftAngle);  p7 := KochLineEnd(p6.point.x, p6.point.y, newLength, p6.angleDegree);  p8 := KochLineEnd(p7.point.x, p7.point.y, newLength, p7.angleDegree - shiftAngle);   Result := [p1, p2, p3, p4, p5, p6, p7, p8];end; function ConvertLineToLeftRightKochShape(x1, y1, x2, y2, angleDegree: Real): TPointWithAngle;var  bs, length, newLength: Real;  lineArray: array of TPointWithAngle;begin  bs := (22.72 / 12) * PI + angleDegree;  length := Sqrt(Sqr(x2 - x1) + Sqr(y2 - y1));  newLength := scalingFactor * length;  lineArray := LeftRightGosperLine(x1, y1, newLength, bs);  Result := lineArray[0]; // Return only the first elementend; function kochGenerator(iterTotal: Integer; dotsArray: array of TPointWithAngle): array of TPointWithAngle;var  nextDotsArray: array of TPointWithAngle;  arrPointer, i: Integer;  p1, p2, p3, p4, p5, p6, p7, p8: TPointWithAngle;begin  if iterTotal = 0 then    Exit(dotsArray);   SetLength(nextDotsArray, Length(dotsArray) * 8);  arrPointer := 0;   while arrPointer < Length(dotsArray) do  begin    for i := 0 to 7 do    begin      case i of        0: p1 := dotsArray[arrPointer];        1: p2 := dotsArray[arrPointer];        2: p3 := dotsArray[arrPointer];        3: p4 := dotsArray[arrPointer];        4: p5 := dotsArray[arrPointer];        5: p6 := dotsArray[arrPointer];        6: p7 := dotsArray[arrPointer];        7: p8 := dotsArray[arrPointer];      end;    end;     nextDotsArray[arrPointer * 8] := p1;    nextDotsArray[arrPointer * 8 + 1] := p2;    nextDotsArray[arrPointer * 8 + 2] := p3;    nextDotsArray[arrPointer * 8 + 3] := p4;    nextDotsArray[arrPointer * 8 + 4] := p5;    nextDotsArray[arrPointer * 8 + 5] := p6;    nextDotsArray[arrPointer * 8 + 6] := p7;    nextDotsArray[arrPointer * 8 + 7] := p8;     arrPointer := arrPointer + 1;  end;   Result := kochGenerator(iterTotal - 1, nextDotsArray);end; procedure TForm1.setup();var  c1, c2: TColor;  y, n: Integer;  newc: TColor;  p1, p2, p3, p4, p5, p6, p7, p8: TPointWithAngle;  startDots: array of TPointWithAngle;begin  Form1.Width := 900;  // Set form width to 900 pixels  Form1.Height := 800; // Set form height to 800 pixels   c1 := ColorToRGB(color1);  c2 := ColorToRGB(color2);   for y := 0 to Form1.Height-1 do  begin    n := Round(Map(y, 0, Form1.Height, 0, 1));    newc := LerpColor(c1, c2, n);    Form1.Canvas.Pen.Color := newc;    Form1.Canvas.Line(0, y, Form1.Width, y);  end;   angleDegree1 := 0*PI;  shiftAngle := 1/3*PI; // constant of 60 degrees, has to be neg   p1.point.x := x1;  p1.point.y := y1;  p1.angleDegree := angleDegree1;  p2 := KochLineEnd(p1.point.x, p1.point.y, newLength, p1.angleDegree);  p3 := KochLineEnd(p2.point.x, p2.point.y, newLength, p2.angleDegree+shiftAngle);  p4 := KochLineEnd(p3.point.x, p3.point.y, newLength, p3.angleDegree+2*shiftAngle);  p5 := KochLineEnd(p4.point.x, p4.point.y, newLength, p4.angleDegree- shiftAngle);  p6 := KochLineEnd(p5.point.x, p5.point.y, newLength, p5.angleDegree-2*shiftAngle);  p7 := KochLineEnd(p6.point.x, p6.point.y, newLength, p6.angleDegree);  p8 := KochLineEnd(p7.point.x, p7.point.y, newLength, p7.angleDegree-shiftAngle);   SetLength(startDots, 1);  startDots[0] := p1;  resultDots1 := kochGenerator(iterTotal, startDots);  draw();end; procedure TForm1.draw();begin  connectTheDots(resultDots1);end; procedure TForm1.connectTheDots(dotsArray: array of TPointWithAngle);var  index1, index2: Integer;  i: Integer;begin  index1 := 0;  index2 := 1;  i := 0;  while i < Length(dotsArray) - 1 do  begin    Canvas.Line(Round(dotsArray[i].point.x),                Round(dotsArray[i].point.y),                Round(dotsArray[i+1].point.x),                Round(dotsArray[i+1].point.y));    index1 := index1 + 1;    index2 := index2 + 1;    i := i + 1;  end;end; procedure TForm1.FormCreate(Sender: TObject);begin  setup();end; end. ---------------------------------------------------------------------- Boleeman · 2024-05-05 09:10 Ok got it compiling with TdotsArray2D = array of array of TPointWithAngle; but nothing drawn to screen. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Math, LCLIntf; type  TPointWithAngle = record    point: record      x, y: Double;    end;    angleDegree: Double;  end;   TdotsArray2D = array of array of TPointWithAngle;   TForm1 = class(TForm)    procedure FormCreate(Sender: TObject);  private    function Map(value, istart, istop, ostart, ostop: Double): Double;    function LerpColor(color1, color2: TColor; t: Double): TColor;    function KochLineEnd(x, y, length, angleDegree: Real): TPointWithAngle;    function LeftRightGosperLine(x, y, newLength, angleDegree: Real): TdotsArray2D;    function kochGenerator(iterTotal: Integer; dotsArray: TdotsArray2D): TdotsArray2D;    procedure setup();    procedure draw();    procedure connectTheDots(dotsArray: TdotsArray2D);  public    { Public declarations }  end; const  scalingFactor = 1/Sqrt(7);  iterTotal = 4;  newLength = 410;  shiftAngle: Double = 0;   x1 = 450; // Adjusted x1 coordinate for the center  y1 = 400; // Adjusted y1 coordinate for the center   color1 = clRed;  color2 = clWhite;  strokeColor = clBlue; var  Form1: TForm1;  angleDegree1: Double;  resultDots1: TdotsArray2D; implementation {$R *.lfm} function TForm1.Map(value, istart, istop, ostart, ostop: Double): Double;begin  Result := ostart + (ostop - ostart) * ((value - istart) / (istop - istart));end; function TForm1.LerpColor(color1, color2: TColor; t: Double): TColor;var  r1, g1, b1, r2, g2, b2: Byte;begin  r1 := GetRValue(color1);  g1 := GetGValue(color1);  b1 := GetBValue(color1);  r2 := GetRValue(color2);  g2 := GetGValue(color2);  b2 := GetBValue(color2);   Result := RGB(    Round(r1 + (r2 - r1) * t),    Round(g1 + (g2 - g1) * t),    Round(b1 + (b2 - b1) * t)  );end; function TForm1.KochLineEnd(x, y, length, angleDegree: Real): TPointWithAngle;var  newX, newY: Real;begin  newX := x + length * Cos(DegToRad(angleDegree));  newY := y - length * Sin(DegToRad(angleDegree)); // Invert y direction  Result.point.x := newX;  Result.point.y := newY;  Result.angleDegree := angleDegree;end; function TForm1.LeftRightGosperLine(x, y, newLength, angleDegree: Real): TdotsArray2D;var  p1, p2, p3, p4, p5, p6, p7, p8: TPointWithAngle;begin  p1.point.x := x;  p1.point.y := y;  p1.angleDegree := angleDegree;   p2 := KochLineEnd(p1.point.x, p1.point.y, newLength, p1.angleDegree);  p3 := KochLineEnd(p2.point.x, p2.point.y, newLength, p2.angleDegree + shiftAngle);  p4 := KochLineEnd(p3.point.x, p3.point.y, newLength, p3.angleDegree + 2 * shiftAngle);  p5 := KochLineEnd(p4.point.x, p4.point.y, newLength, p4.angleDegree - shiftAngle);  p6 := KochLineEnd(p5.point.x, p5.point.y, newLength, p5.angleDegree - 2 * shiftAngle);  p7 := KochLineEnd(p6.point.x, p6.point.y, newLength, p6.angleDegree);  p8 := KochLineEnd(p7.point.x, p7.point.y, newLength, p7.angleDegree - shiftAngle);   SetLength(Result, 1);  Result[0] := [p1, p2, p3, p4, p5, p6, p7, p8];end; function TForm1.kochGenerator(iterTotal: Integer; dotsArray: TdotsArray2D): TdotsArray2D;var  nextDotsArray: TdotsArray2D;  arrPointer, i: Integer;  p1, p2, p3, p4, p5, p6, p7, p8: TPointWithAngle;begin  if iterTotal = 0 then    Exit(dotsArray);   SetLength(nextDotsArray, Length(dotsArray) * 8);  arrPointer := 0;   while arrPointer < Length(dotsArray) do  begin    for i := 0 to 7 do  begin      case i of        0: begin             p1 := dotsArray[arrPointer][0];             p2 := dotsArray[arrPointer][1];             p3 := dotsArray[arrPointer][2];             p4 := dotsArray[arrPointer][3];             p5 := dotsArray[arrPointer][4];             p6 := dotsArray[arrPointer][5];             p7 := dotsArray[arrPointer][6];             p8 := dotsArray[arrPointer][7];           end;      end;    end;     nextDotsArray[arrPointer * 8] := [p1];    nextDotsArray[arrPointer * 8 + 1] := [p2];    nextDotsArray[arrPointer * 8 + 2] := [p3];    nextDotsArray[arrPointer * 8 + 3] := [p4];    nextDotsArray[arrPointer * 8 + 4] := [p5];    nextDotsArray[arrPointer * 8 + 5] := [p6];    nextDotsArray[arrPointer * 8 + 6] := [p7];    nextDotsArray[arrPointer * 8 + 7] := [p8];     arrPointer := arrPointer + 1;  end;   Result := kochGenerator(iterTotal - 1, nextDotsArray);end; procedure TForm1.setup();var  c1, c2: TColor;  y, n: Integer;  newc: TColor;  p1, p2, p3, p4, p5, p6, p7, p8: TPointWithAngle;  startDots: TdotsArray2D; // Change the type herebegin  Form1.Width := 900;  // Set form width to 900 pixels  Form1.Height := 800; // Set form height to 800 pixels   c1 := ColorToRGB(color1);  c2 := ColorToRGB(color2);   for y := 0 to Form1.Height-1 do  begin    n := Round(Map(y, 0, Form1.Height, 0, 1));    newc := LerpColor(c1, c2, n);    Form1.Canvas.Pen.Color := newc;    Form1.Canvas.Line(0, y, Form1.Width, y);  end;   angleDegree1 := 0*PI;  shiftAngle := 1/3*PI; // constant of 60 degrees, has to be neg   p1.point.x := x1;  p1.point.y := y1;  p1.angleDegree := angleDegree1;  p2 := KochLineEnd(p1.point.x, p1.point.y, newLength, p1.angleDegree);  p3 := KochLineEnd(p2.point.x, p2.point.y, newLength, p2.angleDegree+shiftAngle);  p4 := KochLineEnd(p3.point.x, p3.point.y, newLength, p3.angleDegree+2*shiftAngle);  p5 := KochLineEnd(p4.point.x, p4.point.y, newLength, p4.angleDegree- shiftAngle);  p6 := KochLineEnd(p5.point.x, p5.point.y, newLength, p5.angleDegree-2*shiftAngle);  p7 := KochLineEnd(p6.point.x, p6.point.y, newLength, p6.angleDegree);  p8 := KochLineEnd(p7.point.x, p7.point.y, newLength, p7.angleDegree-shiftAngle);   SetLength(startDots, 1);  SetLength(startDots[0], 8); // Adjust length  startDots[0][0] := p1; // Adjust indices  startDots[0][1] := p2;  startDots[0][2] := p3;  startDots[0][3] := p4;  startDots[0][4] := p5;  startDots[0][5] := p6;  startDots[0][6] := p7;  startDots[0][7] := p8;   resultDots1 := kochGenerator(iterTotal, startDots); // Adjust function call  draw();end; procedure TForm1.draw();begin  connectTheDots(resultDots1);end; procedure TForm1.connectTheDots(dotsArray: TdotsArray2D);var  index1, index2: Integer;  i: Integer;begin  index1 := 0;  index2 := 1;  i := 0;  while i < Length(dotsArray) - 1 do  begin    Canvas.Line(Round(dotsArray[i][0].point.x),                Round(dotsArray[i][0].point.y),                Round(dotsArray[i+1][0].point.x),                Round(dotsArray[i+1][0].point.y));    index1 := index1 + 1;    index2 := index2 + 1;    i := i + 1;  end;end; procedure TForm1.FormCreate(Sender: TObject);begin  setup();end; end. ---------------------------------------------------------------------- Boleeman · 2024-05-05 09:28 This is the converted Javascript code converted to Lazarus. It finally compiles without errors (I had index values in reverse previosly). I get 7 points but nothing shown on canvas. Some points are off the canvas, but at least some points/lines should have been drawn. I have some debug message boxes to try to work out (unsuccessfully) where things are going wrong. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Math, LCLIntf, LCLType; type  TPointWithAngle = record    point: record      x, y: Double;    end;  angleDegree: Double;  end;   TdotsArray2D = array of array of TPointWithAngle;   TForm1 = class(TForm)    procedure FormCreate(Sender: TObject);  private    function Map(value, istart, istop, ostart, ostop: Double): Double;    function LerpColor(color1, color2: TColor; t: Double): TColor;    function KochLineEnd(x, y, length, angleDegree: Real): TPointWithAngle;    function LeftRightGosperLine(x, y, newLength, angleDegree: Real): TdotsArray2D;    function kochGenerator(iterTotal: Integer; dotsArray: TdotsArray2D): TdotsArray2D;    procedure setup();    procedure draw();    procedure connectTheDots(dotsArray: TdotsArray2D);  public    { Public declarations }  end; const  scalingFactor = 1/Sqrt(7);  iterTotal = 4;  newLength = 410;  shiftAngle: Double = 0;   x1 = 450; // Adjusted x1 coordinate for the center of paintbox  y1 = 400; // Adjusted y1 coordinate for the center of paintbox   color1 = clRed;  color2 = clWhite;  strokeColor = clBlue; var  Form1: TForm1;  angleDegree1: Double;  resultDots1: TdotsArray2D; implementation {$R *.lfm} function TForm1.Map(value, istart, istop, ostart, ostop: Double): Double;begin  Result := ostart + (ostop - ostart) * ((value - istart) / (istop - istart));end; function TForm1.LerpColor(color1, color2: TColor; t: Double): TColor;var  r1, g1, b1, r2, g2, b2: Byte;begin  r1 := GetRValue(color1);  g1 := GetGValue(color1);  b1 := GetBValue(color1);  r2 := GetRValue(color2);  g2 := GetGValue(color2);  b2 := GetBValue(color2);   Result := RGB(    Round(r1 + (r2 - r1) * t),    Round(g1 + (g2 - g1) * t),    Round(b1 + (b2 - b1) * t)  );end; function TForm1.KochLineEnd(x, y, length, angleDegree: Real): TPointWithAngle;var  newX, newY: Real;begin  newX := x + length * Cos(DegToRad(angleDegree));  newY := y - length * Sin(DegToRad(angleDegree)); // Invert y direction  Result.point.x := newX;  Result.point.y := newY;  Result.angleDegree := angleDegree;end; function TForm1.LeftRightGosperLine(x, y, newLength, angleDegree: Real): TdotsArray2D;var  p1, p2, p3, p4, p5, p6, p7, p8: TPointWithAngle;begin  p1.point.x := x;  p1.point.y := y;  p1.angleDegree := angleDegree;   p2 := KochLineEnd(p1.point.x, p1.point.y, newLength, p1.angleDegree);  p3 := KochLineEnd(p2.point.x, p2.point.y, newLength, p2.angleDegree + shiftAngle);  p4 := KochLineEnd(p3.point.x, p3.point.y, newLength, p3.angleDegree + 2 * shiftAngle);  p5 := KochLineEnd(p4.point.x, p4.point.y, newLength, p4.angleDegree - shiftAngle);  p6 := KochLineEnd(p5.point.x, p5.point.y, newLength, p5.angleDegree - 2 * shiftAngle);  p7 := KochLineEnd(p6.point.x, p6.point.y, newLength, p6.angleDegree);  p8 := KochLineEnd(p7.point.x, p7.point.y, newLength, p7.angleDegree - shiftAngle);   SetLength(Result, 1);  Result[0] := [p1, p2, p3, p4, p5, p6, p7, p8];end; function TForm1.kochGenerator(iterTotal: Integer; dotsArray: TdotsArray2D): TdotsArray2D;var  nextDotsArray: TdotsArray2D;  p1, p2, p3, p4, p5, p6, p7, p8: TPointWithAngle;begin  if iterTotal = 0 then  begin    Application.MessageBox('Finished generating Koch curve', 'Debug Info', MB_OK);    Exit(dotsArray);  end;   Application.MessageBox(PChar('Length of dotsArray: ' + IntToStr(Length(dotsArray))), 'Debug Info', MB_OK);   SetLength(nextDotsArray, Length(dotsArray) * 8);   if Length(dotsArray) = 1 then  begin    // Adjust the length of nextDotsArray    SetLength(nextDotsArray, 1);     p1 := dotsArray[0][0];    p2 := KochLineEnd(p1.point.x, p1.point.y, newLength, p1.angleDegree);    p3 := KochLineEnd(p2.point.x, p2.point.y, newLength, p2.angleDegree + shiftAngle);    p4 := KochLineEnd(p3.point.x, p3.point.y, newLength, p3.angleDegree + 2 * shiftAngle);    p5 := KochLineEnd(p4.point.x, p4.point.y, newLength, p4.angleDegree - shiftAngle);    p6 := KochLineEnd(p5.point.x, p5.point.y, newLength, p5.angleDegree - 2 * shiftAngle);    p7 := KochLineEnd(p6.point.x, p6.point.y, newLength, p6.angleDegree);    p8 := KochLineEnd(p7.point.x, p7.point.y, newLength, p7.angleDegree - shiftAngle);     // Populate nextDotsArray with the generated points  nextDotsArray[0] := [p1, p2, p3, p4, p5, p6, p7, p8];   end  else  begin    // Implement logic for multiple dotsArray elements here  end;   Application.MessageBox(PChar('Iteration ' + IntToStr(iterTotal) + ' completed'), 'Debug Info', MB_OK);  Result := kochGenerator(iterTotal - 1, nextDotsArray);end; procedure TForm1.setup();var  c1, c2: TColor;  y, n: Integer;  newc: TColor;  p1, p2, p3, p4, p5, p6, p7, p8: TPointWithAngle;  startDots: TdotsArray2D; // Change the type herebegin  Form1.Width := 900;  // Set form width to 900 pixels  Form1.Height := 800; // Set form height to 800 pixels   c1 := ColorToRGB(color1);  c2 := ColorToRGB(color2);   for y := 0 to Form1.Height-1 do  begin    n := Round(Map(y, 0, Form1.Height, 0, 1));    newc := LerpColor(c1, c2, n);    Form1.Canvas.Pen.Color := newc;    Form1.Canvas.Line(0, y, Form1.Width, y);  end;   angleDegree1 := 0*PI;  shiftAngle := 1/3*PI; // constant of 60 degrees   p1.point.x := x1;  p1.point.y := y1;  p1.angleDegree := angleDegree1;  p2 := KochLineEnd(p1.point.x, p1.point.y, newLength, p1.angleDegree);  p3 := KochLineEnd(p2.point.x, p2.point.y, newLength, p2.angleDegree+shiftAngle);  p4 := KochLineEnd(p3.point.x, p3.point.y, newLength, p3.angleDegree+2*shiftAngle);  p5 := KochLineEnd(p4.point.x, p4.point.y, newLength, p4.angleDegree-shiftAngle);  p6 := KochLineEnd(p5.point.x, p5.point.y, newLength, p5.angleDegree-2*shiftAngle);  p7 := KochLineEnd(p6.point.x, p6.point.y, newLength, p6.angleDegree);  p8 := KochLineEnd(p7.point.x, p7.point.y, newLength, p7.angleDegree-shiftAngle);   SetLength(startDots, 1);  SetLength(startDots[0], 8); // Adjust length  startDots[0][0] := p1; // Adjust indices  startDots[0][1] := p2;  startDots[0][2] := p3;  startDots[0][3] := p4;  startDots[0][4] := p5;  startDots[0][5] := p6;  startDots[0][6] := p7;  startDots[0][7] := p8;   resultDots1 := kochGenerator(iterTotal, startDots);  draw();end; procedure TForm1.draw();begin  connectTheDots(resultDots1);end; procedure TForm1.connectTheDots(dotsArray: TdotsArray2D);var  i: Integer;begin  // Display the length of dotsArray[0]  Application.MessageBox(PChar('Number of points: ' + IntToStr(Length(dotsArray[0]))), 'Debug Info', MB_OK);   // Display a message box to check if the procedure is being executed  Application.MessageBox('Connecting the dots!', 'Debug Info', MB_OK);   for i := 0 to High(dotsArray[0]) - 1 do  begin    // Display coordinates of each point    Application.MessageBox(      PChar('Point ' + IntToStr(i) + ': (' + FloatToStr(dotsArray[0][i].point.x) +      ', ' + FloatToStr(dotsArray[0][i].point.y) + ')'),      'Point Coordinates',      MB_OK    );     // Draw lines between points    Canvas.MoveTo(Round(dotsArray[0][i].point.x), Round(dotsArray[0][i].point.y));    Canvas.LineTo(Round(dotsArray[0][i + 1].point.x), Round(dotsArray[0][i + 1].point.y));  end;end; procedure TForm1.FormCreate(Sender: TObject);begin  setup();end; end.     And here is the p5 sketch JavaScript code I used: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  const scalingFactor = 1/Math.sqrt(7);const iterTotal = 4;const newLength = 410;let shiftAngle; const x1 = 2560/2;const y1 = 1440/2+450; const color1 = '#FFCDD7' ;const color2 = 'white';const strokeColor = '#05297D'; let angleDegree1;let resultDots1;let resultDots2; function setup() {  createCanvas(2560, 1440);  c1 = color(color1);  c2 = color(color2);    for(let y=0; y {    while(index2 <= subArr.length-1){    line(subArr[index1].point.x,        subArr[index1].point.y,        subArr[index2].point.x,        subArr[index2].point.y          );    index1++;      index2++;      }    index1 = 0;    index2 = 1;  })  }   function drawDots(dotsArray) {    const flatArray = dotsArray.flat();    flatArray.forEach((dot) => {      circle(dot.point.x, dot.point.y,5)    });    } function kochGenerator(iterTotal,dotsArray) {  if (iterTotal===0) { return dotsArray};  let nextDotsArray = [];  let arrPointer = 0;  while (arrPointer < dotsArray.length) {    const p1 = dotsArray[arrPointer][0];    const p2 = dotsArray[arrPointer][1];    const p3 = dotsArray[arrPointer][2];    const p4 = dotsArray[arrPointer][3];    const pt5 = dotsArray[arrPointer][4];    const p6 = dotsArray[arrPointer][5];    const p7 = dotsArray[arrPointer][6];    const p8 = dotsArray[arrPointer][7];    nextDotsArray.push(convertLineToLeftRightKochShape(p1.point.x, p1.point.y, p2.point.x, p2.point.y, p2.angleDegree));    nextDotsArray.push(convertLineToLeftRightKochShape(p3.point.x, p3.point.y, p2.point.x, p2.point.y, PI+p3.angleDegree));    nextDotsArray.push(convertLineToLeftRightKochShape(p4.point.x, p4.point.y, p3.point.x, p3.point.y, PI+p4.angleDegree));    nextDotsArray.push(convertLineToLeftRightKochShape(p4.point.x, p4.point.y, pt5.point.x, pt5.point.y, pt5.angleDegree));    nextDotsArray.push(convertLineToLeftRightKochShape(pt5.point.x, pt5.point.y, p6.point.x, p6.point.y, p6.angleDegree));    nextDotsArray.push(convertLineToLeftRightKochShape(p6.point.x, p6.point.y, p7.point.x, p7.point.y, p7.angleDegree));    nextDotsArray.push(convertLineToLeftRightKochShape(p8.point.x, p8.point.y, p7.point.x, p7.point.y, PI+p8.angleDegree));    arrPointer++;  }  return kochGenerator(iterTotal-1,nextDotsArray);} function kochLineEnd(x1,y1,length,angleDegree) {  const endingPointX = x1+length*cos(angleDegree);  const endingPointY = y1-length*sin(angleDegree);  return {'point':{x: endingPointX, y:endingPointY},angleDegree};} function convertLineToLeftRightKochShape(x1,y1,x2,y2,angleDegree) {  const bs = 22.72/12*PI+angleDegree;   const length = Math.sqrt(Math.pow((x2-x1),2)+Math.pow((y2-y1),2));  const newLength = scalingFactor*length;  const lineArray = leftRightGosperLine(x1,y1,newLength,bs);  return lineArray;} function convertLineToRightLeftKochShape(x1,y1,x2,y2,angleDegree) {  const bs = 22.72/12*PI+angleDegree;   const length = Math.sqrt(Math.pow((x2-x1),2)+Math.pow((y2-y1),2));  const newLength = scalingFactor*length;  const lineArray = rightLeftGosperLine(x1,y1,newLength,bs);  return lineArray;} function leftRightGosperLine(x,y,newLength,angleDegree) {  const p1 = {'point': {'x': x, 'y':y},angleDegree };  const p2 = kochLineEnd(p1.point.x, p1.point.y,newLength,p1.angleDegree);  const p3 = kochLineEnd(p2.point.x, p2.point.y,newLength,p2.angleDegree+shiftAngle);  const p4 = kochLineEnd(p3.point.x, p3.point.y,newLength,p3.angleDegree+2*shiftAngle);  const pt5 = kochLineEnd(p4.point.x, p4.point.y,newLength,p4.angleDegree- shiftAngle);  const p6 = kochLineEnd(pt5.point.x, pt5.point.y,newLength, pt5.angleDegree-2*shiftAngle);  const p7 = kochLineEnd(p6.point.x, p6.point.y,newLength,p6.angleDegree);  const p8 = kochLineEnd(p7.point.x, p7.point.y,newLength,p7.angleDegree- shiftAngle);  return [p1,p2,p3,p4,pt5,p6,p7,p8];} function rightLeftGosperLine(x,y,newLength,angleDegree) {  const p1 = {'point': {'x': x, 'y':y},angleDegree };  const p2 = kochLineEnd(p1.point.x, p1.point.y,newLength,p1.angleDegree-shiftAngle);  const p3 = kochLineEnd(p2.point.x, p2.point.y,newLength,p2.angleDegree+shiftAngle);  const p4 = kochLineEnd(p3.point.x, p3.point.y,newLength,p3.angleDegree);  const pt5 = kochLineEnd(p4.point.x, p4.point.y,newLength,p4.angleDegree+2*shiftAngle);  const p6 = kochLineEnd(pt5.point.x, pt5.point.y,newLength, pt5.angleDegree+shiftAngle);  const p7 = kochLineEnd(p6.point.x, p6.point.y,newLength,p6.angleDegree-2*shiftAngle);  const p8 = kochLineEnd(p7.point.x, p7.point.y,newLength,p7.angleDegree- shiftAngle);  return [p1,p2,p3,p4,pt5,p6,p7,p8];}  Ah, I give up for today. ---------------------------------------------------------------------- jamie · 2024-05-05 23:37 Thanks for posting link to the Java code, I like reading through it keeping my mind fresh on it. Btw, If I knew you were trying to decode that earlier I could have made an almost perfect duplication of it in Object code. Java is one of those in between languages. ---------------------------------------------------------------------- Boleeman · 2024-05-06 10:50 Hey Jamie, if you wouldn't mind to have a crack at converting the Java version that would be great. Here is my non working attempt from the Java code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, Math, Spin; type   { TForm1 }   TForm1 = class(TForm)    MinusButton: TButton;    PlusButton: TButton;    PaintBox1: TPaintBox;    IterField: TSpinEdit;    procedure FormCreate(Sender: TObject);    procedure PaintBox1Paint(Sender: TObject);    procedure IterFieldChange(Sender: TObject);    procedure PlusButtonClick(Sender: TObject);    procedure MinusButtonClick(Sender: TObject);  private    const      START_X: Integer = 100;      START_Y: Integer = 200;      START_ANGLE: Double = 0;      START_LENGTH: Double = 600;      COLORS: array[0..6] of TColor = (clBlack, clBlue, clGreen, clFuchsia, clPurple, clAqua , clRed);    var      Iter: Integer;      X, Y, Angle: Double;    procedure Curve(currIter: Integer; cType: Char; var length: Double; g: TCanvas);    procedure UpdateCurve(newIter: Integer);  public   end; var  Form1: TForm1; implementation {$R *.lfm} procedure TForm1.Curve(currIter: Integer; cType: Char; var length: Double; g: TCanvas);var  I: Integer;begin  if currIter > 0 then  begin    length := length / Sqrt(7);    Dec(currIter);    if cType = 'a' then    begin      Curve(currIter, 'a', length, g);      Angle := Angle + 60;      Curve(currIter, 'b', length, g);      Angle := Angle + 2 * 60;    Curve(currIter, 'b', length, g);      Angle := Angle - 60;      Curve(currIter, 'a', length, g);      Angle := Angle - 2 * 60;      Curve(currIter, 'a', length, g);      Curve(currIter, 'a', length, g);      Angle := Angle - 60;      Curve(currIter, 'b', length, g);    Angle := Angle + 60;    end    else    begin      Angle := Angle - 60;      Curve(currIter, 'a', length, g);      Angle := Angle + 60;    Curve(currIter, 'b', length, g);      Curve(currIter, 'b', length, g);      Angle := Angle + 2 * 60;      Curve(currIter, 'b', length, g);      Angle := Angle + 60;      Curve(currIter, 'a', length, g);    Angle := Angle - 2 * 60;      Curve(currIter, 'a', length, g);      Angle := Angle - 60;      Curve(currIter, 'b', length, g);    end;  end  else  begin    Iter := Iter mod 7;    g.Pen.Color := COLORS[Iter];    g.Line(Round(X), Round(Y), Round(X + length * Cos(DegToRad(Angle))), Round(Y + length * Sin(DegToRad(Angle))));    X := X + length * Cos(DegToRad(Angle));    Y := Y + length * Sin(DegToRad(Angle));  end;end; procedure TForm1.UpdateCurve(newIter: Integer);begin  if newIter < 0 then    newIter := 0;  if Iter <> newIter then  begin    Iter := newIter;    IterField.Value := newIter;    PaintBox1.Invalidate;  end;end; procedure TForm1.FormCreate(Sender: TObject);begin  Iter := 1;  X := START_X;  Y := START_Y;  Angle := START_ANGLE - (Iter * (ArcTan(Sqrt(3) / 5) * 180 / Pi));  PaintBox1.Width := Round(2 * START_X + START_LENGTH);  PaintBox1.Height := Round(START_Y + START_LENGTH);end; procedure TForm1.PaintBox1Paint(Sender: TObject);begin  X := START_X;  Y := START_Y;  Angle := START_ANGLE - (Iter * (ArcTan(Sqrt(3) / 5) * 180 / Pi));  Curve(Iter, 'a', START_LENGTH, PaintBox1.Canvas);end; procedure TForm1.IterFieldChange(Sender: TObject);begin  UpdateCurve(IterField.Value);  PaintBox1.Invalidate;end; procedure TForm1.PlusButtonClick(Sender: TObject);begin  UpdateCurve(IterField.Value + 1);  PaintBox1.Invalidate;end; procedure TForm1.MinusButtonClick(Sender: TObject);begin  UpdateCurve(IterField.Value - 1);  PaintBox1.Invalidate;end; end. Ah, I need to take a break from converting as I seem to be going round in circles with both the Java Conversion and the JavaScript Conversion. I thought I had the Javascript conversion sorted but only some points are created. Tried debugging and fiddling with the code, but still no success. The Javascript version is nice as it gives a nice sized curve each time at different recursion levels. ---------------------------------------------------------------------- jamie · 2024-05-07 22:50 I wanted to let you know that in Java, it is case sensitive. In this case, "ANGLE" and "angle" are not the same. Look in the original java code and you will see both being used but not the same. ---------------------------------------------------------------------- Boleeman · 2024-05-11 10:54 Thanks Jamie for that:  "ANGLE" and "angle" are not the same in Java.