using System.Collections.Immutable; using System.Reflection.Metadata; using Avalonia.Controls.Selection; using LeoTurtle; namespace PinwheelTiling; public static class PinwheelTilingPath { private const double Alpha = 26.57D; private const double Beta = 90D - Alpha; private const double Gamma = 90D; private static Point _startPoint = new Point(0, 0.2); private static Point _endPoint = new Point(0, 0); /// /// Executes the logic for adding turtle path steps. /// Called automatically when application starts. /// /// The instance to use public static void Walk(SmartTurtle turtle) { var initialTriangle = new Triangle(new Point(2.5D, 10.0D), new Point(82.5D, 50.0D), new Point(82.5D, 10.0D)); const double sideA = 40.0D; const double sideB = 80.0D; const int depth = 1; _endPoint = new Point(_startPoint.X + sideB, _startPoint.Y + sideA); Triangle triangle = MakeTriangle(_startPoint, _endPoint); MakeRecursiveTriangle(turtle, triangle, depth); } private static void MakeRecursiveTriangle(SmartTurtle turtle, Triangle triangle, int depth = 0) { if (depth == 0) { return; } depth--; Triangle[] subdivision = GetSubdivision(triangle); DrawSubdivision(turtle, subdivision); for (int i = 0; i < subdivision.Length; i++) { MakeRecursiveTriangle(turtle, subdivision[i], depth); } } private static Triangle MakeTriangle(Point startingPoint, Point endingPoint) { Point pointA = startingPoint; Point pointB = endingPoint; Point pointC = new Point(endingPoint.X, startingPoint.Y); return new Triangle(pointA, pointB, pointC); } private static Triangle[] GetSubdivision(Triangle triangle) { double sideA = DistanceBetweenPoints(triangle.B, triangle.C); double sideB = DistanceBetweenPoints(triangle.A, triangle.C); double sideC = CalculateHyptonuse(sideA, sideB); Point startingPoint = new Point(triangle.A.X, triangle.A.Y); Point endingPoint = new Point(triangle.B.X, triangle.B.Y); //calculate parent sides double height = CalculateHeight(sideA, sideB, sideC); double sideE = height / 2; //double sideF = CalculateHyptonuse(sideE, height); //calculate additional sides that are part of the parent triangle double sideB1 = sideB / 2; double sideC1 = Math.Sqrt(Math.Pow(sideA, 2) - Math.Pow(height, 2)); //double sideC2; double sideC3 = Math.Sqrt(Math.Pow(sideB1, 2) - Math.Pow(sideE, 2)); //calculate additional sides that are |not part/not important at all| for the parent triangle double heightOfTriangle0 = CalculateHeight(sideC1, height, sideA); double heightOfTriangle1 = CalculateHeight(sideE, height, sideB1); double heightOfTriangle2 = CalculateHeight(sideE, sideC3, sideB1); double sideB1SegmentOfTriangle1 = Math.Sqrt(Math.Pow(sideE, 2) - Math.Pow(heightOfTriangle1, 2)); double sideB1SegmentOfTriangle2 = Math.Sqrt(Math.Pow(sideE, 2) - Math.Pow(heightOfTriangle2, 2)); double heightOfAllExceptTriangle0 = CalculateHeight(height, sideC - sideC1, sideB); double sideB1SegmentOfAllTrianglesExcept0 = Math.Sqrt(Math.Pow(sideC - sideC1, 2) - Math.Pow(heightOfAllExceptTriangle0, 2)); //create Points Point pointA = startingPoint; Point pointB = endingPoint; Point pointC = new Point(endingPoint.X, startingPoint.Y); Point pointD = new Point(startingPoint.X + sideB1SegmentOfAllTrianglesExcept0, startingPoint.Y + heightOfAllExceptTriangle0); Point pointE = new Point(startingPoint.X + sideB1 - sideB1SegmentOfTriangle2, startingPoint.Y + heightOfTriangle2); Point pointF = new Point(startingPoint.X + sideB1, startingPoint.Y); Point pointH = new Point(startingPoint.X + sideB - sideB1SegmentOfTriangle1, startingPoint.Y + heightOfTriangle1); Triangle triangle0 = new Triangle(pointC, pointB, pointD); Triangle triangle1 = new Triangle(pointF, pointC, pointH); Triangle triangle2 = new Triangle(pointA, pointF, pointE); Triangle triangle3 = new Triangle(pointF, pointD, pointH); Triangle triangle4 = new Triangle(pointD, pointF, pointE); Triangle[] subdivisionTriangles = { triangle0, triangle1, triangle2, triangle3, triangle4 }; return subdivisionTriangles; double CalculateHeight(double a, double b, double c) => a * b / c; } private static void DrawSubdivision(SmartTurtle turtle, Triangle[] subdivision) { foreach (var triangle in subdivision) { DrawSimpleTriangle(turtle, triangle); } } private static void DrawSimpleTriangle(SmartTurtle turtle, Triangle triangle) { turtle.Teleport(triangle.A.X, triangle.A.Y); double sideAB = DistanceBetweenPoints(triangle.A, triangle.B); double sideBC = DistanceBetweenPoints(triangle.B, triangle.C); double sideCA = DistanceBetweenPoints(triangle.C, triangle.A); turtle.LookAt(triangle.B.X, triangle.B.Y); turtle.MoveForward(sideAB); turtle.LookAt(triangle.C.X, triangle.C.Y); turtle.MoveForward(sideBC); turtle.LookAt(triangle.A.X, triangle.A.Y); turtle.MoveForward(sideCA); } private static double CalculateHyptonuse(double a, double b) { return Math.Sqrt(Math.Pow(a, 2) + Math.Pow(b, 2)); } /// /// Converts an angel from degrees to radians. /// /// Degrees to convert /// Radians value private static double ConvertToRadians(double angleDegrees) { return angleDegrees * Math.PI / 180D; } /// /// Calculates the distance between two points. /// /// First point /// Second point /// Distance between the two points private static double DistanceBetweenPoints(Point a, Point b) { return Math.Sqrt(Math.Pow(b.X - a.X, 2D) + Math.Pow(b.Y - a.Y, 2D)); } }