Pythagoras tree

From Rosetta Code
Task
Pythagoras tree
You are encouraged to solve this task according to the task description, using any language you may know.

The Pythagoras tree is a fractal tree constructed from squares. It is named after Pythagoras because each triple of touching squares encloses a right triangle, in a configuration traditionally used to represent the Pythagorean theorem.

Task

Construct a Pythagoras tree of order 7 using only vectors (no rotation or trigonometric functions).

Related tasks



Ada

Library: SDLAda
with SDL.Video.Windows.Makers;
with SDL.Video.Renderers.Makers;
with SDL.Video.Rectangles;
with SDL.Events.Events;

procedure Pythagoras_Tree is

   Width   : constant := 600;
   Height  : constant := 600;
   Level   : constant := 7;

   type Point is record X, Y : Float; end record;
   B1 : constant Point := (X => 250.0, Y => 550.0);
   B2 : constant Point := (X => 350.0, Y => 550.0);

   Window   : SDL.Video.Windows.Window;
   Renderer : SDL.Video.Renderers.Renderer;
   Event    : SDL.Events.Events.Events;

   procedure Draw_Pythagoras_Tree (Level  : in Natural;
                                   P1, P2 : in Point)
   is
      use SDL.Video.Rectangles;
      Dx : constant Float := P2.X - P1.X;
      Dy : constant Float := P1.Y - P2.Y;
      R  : constant Point := (X => P2.X - Dy, Y => P2.Y - Dx);
      L  : constant Point := (X => P1.X - Dy, Y => P1.Y - Dx);
      M  : constant Point := (X => L.X + (Dx - Dy) / 2.0,
                              Y => L.Y - (Dx + Dy) / 2.0);

      CP1 : constant SDL.Video.Rectangles.Point := (C.int (P1.X), C.int (P1.Y));
      CP2 : constant SDL.Video.Rectangles.Point := (C.int (P2.X), C.int (P2.Y));
      CL  : constant SDL.Video.Rectangles.Point := (C.int (L.X),  C.int (L.Y));
      CR  : constant SDL.Video.Rectangles.Point := (C.int (R.X),  C.int (R.Y));
      CM  : constant SDL.Video.Rectangles.Point := (C.int (M.X),  C.int (M.Y));

      Square : constant SDL.Video.Rectangles.Line_Arrays :=
        ((CP1, CP2), (CP2, CR), (CR, CL), (CL, CP1));
      Triang : constant SDL.Video.Rectangles.Line_Arrays :=
        ((CR, CL), (CL, CM), (CM, CR));
   begin
      if Level > 0 then
         Renderer.Set_Draw_Colour (Colour => (0, 220, 0, 255));
         Renderer.Draw (Lines => Square);
         Renderer.Draw (Lines => Triang);

         Draw_Pythagoras_Tree (Level - 1, L, M);
         Draw_Pythagoras_Tree (Level - 1, M, R);
      end if;
   end Draw_Pythagoras_Tree;

   procedure Wait is
      use type SDL.Events.Event_Types;
   begin
      loop
         while SDL.Events.Events.Poll (Event) loop
            if Event.Common.Event_Type = SDL.Events.Quit then
               return;
            end if;
         end loop;
         delay 0.100;
      end loop;
   end Wait;

begin
   if not SDL.Initialise (Flags => SDL.Enable_Screen) then
      return;
   end if;

   SDL.Video.Windows.Makers.Create (Win      => Window,
                                    Title    => "Pythagoras tree",
                                    Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
                                    Size     => SDL.Positive_Sizes'(Width, Height),
                                    Flags    => 0);
   SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
   Renderer.Set_Draw_Colour ((0, 0, 0, 255));
   Renderer.Fill (Rectangle => (0, 0, Width, Height));
   Renderer.Set_Draw_Colour ((0, 220, 0, 255));

   Draw_Pythagoras_Tree (Level, B1, B2);
   Window.Update_Surface;

   Wait;
   Window.Finalize;
   SDL.Finalise;
end Pythagoras_Tree;

AutoHotkey

Requires Gdip Library

pToken := Gdip_Startup()
gdip1()
Pythagoras_tree(600, 600, 712, 600, 1)
UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width, Height)
OnExit, Exit
return

Pythagoras_tree(x1, y1, x2, y2, depth){
    global G, hwnd1, hdc, Width, Height
    if (depth > 7)
        Return

    Pen := Gdip_CreatePen(0xFF808080, 1)
    Brush1 := Gdip_BrushCreateSolid(0xFFFFE600)
    Brush2 := Gdip_BrushCreateSolid(0xFFFAFF00)
    Brush3 := Gdip_BrushCreateSolid(0xFFDBFF00)
    Brush4 := Gdip_BrushCreateSolid(0xFFDBFF00)
    Brush5 := Gdip_BrushCreateSolid(0xFF9EFF00)
    Brush6 := Gdip_BrushCreateSolid(0xFF80FF00)
    Brush7 := Gdip_BrushCreateSolid(0xFF60FF00)
    
    dx := x2 - x1 , dy := y1 - y2
    x3 := x2 - dy , y3 := y2 - dx
    x4 := x1 - dy , y4 := y1 - dx
    x5 := x4 + (dx - dy) / 2
    y5 := y4 - (dx + dy) / 2
    
    ; draw box/triangle
    Gdip_FillPolygon(G, Brush%depth%, x1 "," y1 "|" x2 "," y2 "|" x3 "," y3 "|" x4 "," y4 "|" x1 "," y1)
    Gdip_FillPolygon(G, Brush%depth%, x4 "," y4 "|" x5 "," y5 "|" x3 "," y3 "|" x4 "," y4)
	
    ; draw outline    
    Gdip_DrawLines(G, Pen, x1 "," y1 "|" x2 "," y2 "|" x3 "," y3 "|" x4 "," y4 "|" x1 "," y1)
    Gdip_DrawLines(G, Pen, x4 "," y4 "|" x5 "," y5 "|" x3 "," y3 "|" x4 "," y4)
    
    Pythagoras_tree(x4, y4, x5, y5, depth+1)
    Pythagoras_tree(x5, y5, x3, y3, depth+1)
}

gdip1(){
    global
    Width := A_ScreenWidth, Height := A_ScreenHeight
    Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop
    Gui, 1: Show, NA
    hwnd1 := WinExist()
    OnMessage(0x201, "WM_LBUTTONDOWN")
    hbm := CreateDIBSection(Width, Height)
    hdc := CreateCompatibleDC()
    obm := SelectObject(hdc, hbm)
    G := Gdip_GraphicsFromHDC(hdc)
    Gdip_SetSmoothingMode(G, 4)
}
; ---------------------------------------------------------------
WM_LBUTTONDOWN(){
    PostMessage, 0xA1, 2
}
; ---------------------------------------------------------------
gdip2(){
    global
    Gdip_DeleteBrush(pBrush)
    Gdip_DeletePen(pPen)
    SelectObject(hdc, obm)
    DeleteObject(hbm)
    DeleteDC(hdc)
    Gdip_DeleteGraphics(G)
}
; ---------------------------------------------------------------
exit:
gdip2()
ExitApp
return

BASIC

BASIC256

Translation of: FreeBASIC
Subroutine pythagoras_tree(x1, y1, x2, y2, depth)
	If depth > 10 Then Return

	dx = x2 - x1 : dy = y1 - y2
	x3 = x2 - dy : y3 = y2 - dx
	x4 = x1 - dy : y4 = y1 - dx
	x5 = x4 + (dx - dy) / 2
	y5 = y4 - (dx + dy) / 2
	#draw the box
	Line x1, y1, x2, y2 : Line x2, y2, x3, y3
	Line x3, y3, x4, y4 : Line x4, y4, x1, y1

	Call pythagoras_tree(x4, y4, x5, y5, depth +1)
	Call pythagoras_tree(x5, y5, x3, y3, depth +1)
End Subroutine

w = 800 : h = w * 11 \ 16
w2 = w \ 2 : diff = w \ 12

Clg
FastGraphics
Graphsize w, h
Color green
Call pythagoras_tree(w2 - diff, h - 10, w2 + diff, h - 10, 0)
Refresh
ImgSave "pythagoras_tree.jpg", "jpg"
End

IS-BASIC

100 PROGRAM "Pythagor.bas"
110 OPTION ANGLE DEGREES
120 LET SQ2=SQR(2)
130 SET VIDEO MODE 1:SET VIDEO COLOUR 0:SET VIDEO X 42:SET VIDEO Y 25
140 OPEN #101:"video:"
150 SET PALETTE 0,141
160 DISPLAY #101:AT 1 FROM 1 TO 25
170 PLOT 580,20;ANGLE 90;
180 CALL BROCCOLI(225,10)
190 DO
200 LOOP WHILE INKEY$=""
210 TEXT
220 DEF BROCCOLI(X,Y)
230   IF X<Y THEN EXIT DEF
240   CALL SQUARE(X)
250   PLOT FORWARD X,LEFT 45,
260   CALL BROCCOLI(X/SQ2,Y)
270   PLOT RIGHT 90,FORWARD X/SQ2,
280   CALL BROCCOLI(X/SQ2,Y)
290   PLOT BACK X/SQ2,LEFT 45,BACK X,
300 END DEF
310 DEF SQUARE(X)
320   FOR I=1 TO 4
330     PLOT FORWARD X;RIGHT 90;
340   NEXT
350 END DEF

C

A Pythagoras tree constructed from an initial square of side length L, fits exactly in a bounding box of length 6L and width 4L(Proof). That's why the window dimensions are set to 6L x 4L, where L is entered by the user. The squares increase rapidly, an iteration value of 30 takes 'forever' for a single branch to complete. The colours are picked randomly thus producing the effect of a Pythagorean Christmas Tree. :)

Requires the WinBGIm library.

#include<graphics.h>
#include<stdlib.h>
#include<stdio.h>
#include<time.h>

typedef struct{
	double x,y;
}point;

void pythagorasTree(point a,point b,int times){
	
	point c,d,e;
	
	c.x = b.x - (a.y -  b.y);
	c.y = b.y - (b.x - a.x);
	
	d.x = a.x - (a.y -  b.y);
	d.y = a.y - (b.x - a.x);
	
	e.x = d.x +  ( b.x - a.x - (a.y -  b.y) ) / 2;
	e.y = d.y -  ( b.x - a.x + a.y -  b.y ) / 2;
	
	if(times>0){
		setcolor(rand()%15 + 1);
		
		line(a.x,a.y,b.x,b.y);
		line(c.x,c.y,b.x,b.y);
		line(c.x,c.y,d.x,d.y);
		line(a.x,a.y,d.x,d.y);
		
		pythagorasTree(d,e,times-1);
		pythagorasTree(e,c,times-1);
	}
}

int main(){
	
	point a,b;
	double side;
	int iter;
	
	time_t t;
	
	printf("Enter initial side length : ");
	scanf("%lf",&side);
	
	printf("Enter number of iterations : ");
	scanf("%d",&iter);
	
	a.x = 6*side/2 - side/2;
	a.y = 4*side;
	b.x = 6*side/2 + side/2;
	b.y = 4*side;
	
	initwindow(6*side,4*side,"Pythagoras Tree ?");
	
	srand((unsigned)time(&t));
	
	pythagorasTree(a,b,iter);
	
	getch();
	
	closegraph();
	
	return 0;

}

C++

Windows version

Translation of: Java
#include <windows.h>
#include <string>
#include <iostream>
 
const int BMP_SIZE = 720, LINE_LEN = 120, BORDER = 100;

class myBitmap {
public:
    myBitmap() : pen( NULL ), brush( NULL ), clr( 0 ), wid( 1 ) {}
    ~myBitmap() {
        DeleteObject( pen ); DeleteObject( brush );
        DeleteDC( hdc ); DeleteObject( bmp );
    }
    bool create( int w, int h ) {
        BITMAPINFO bi;
        ZeroMemory( &bi, sizeof( bi ) );
        bi.bmiHeader.biSize        = sizeof( bi.bmiHeader );
        bi.bmiHeader.biBitCount    = sizeof( DWORD ) * 8;
        bi.bmiHeader.biCompression = BI_RGB;
        bi.bmiHeader.biPlanes      = 1;
        bi.bmiHeader.biWidth       =  w;
        bi.bmiHeader.biHeight      = -h;
        HDC dc = GetDC( GetConsoleWindow() );
        bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
        if( !bmp ) return false;
        hdc = CreateCompatibleDC( dc );
        SelectObject( hdc, bmp );
        ReleaseDC( GetConsoleWindow(), dc );
        width = w; height = h;
        return true;
    }
    void clear( BYTE clr = 0 ) {
        memset( pBits, clr, width * height * sizeof( DWORD ) );
    }
    void setBrushColor( DWORD bClr ) {
        if( brush ) DeleteObject( brush );
        brush = CreateSolidBrush( bClr );
        SelectObject( hdc, brush );
    }
    void setPenColor( DWORD c ) {
        clr = c; createPen();
    }
    void setPenWidth( int w ) {
        wid = w; createPen();
    }
    void saveBitmap( std::string path ) {
        BITMAPFILEHEADER fileheader;
        BITMAPINFO       infoheader;
        BITMAP           bitmap;
        DWORD            wb;
        GetObject( bmp, sizeof( bitmap ), &bitmap );
        DWORD* dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];
        ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
        ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
        ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );
        infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
        infoheader.bmiHeader.biCompression = BI_RGB;
        infoheader.bmiHeader.biPlanes = 1;
        infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
        infoheader.bmiHeader.biHeight = bitmap.bmHeight;
        infoheader.bmiHeader.biWidth = bitmap.bmWidth;
        infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );
        fileheader.bfType    = 0x4D42;
        fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
        fileheader.bfSize    = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;
        GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );
        HANDLE file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 
                                  FILE_ATTRIBUTE_NORMAL, NULL );
        WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
        WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
        WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
        CloseHandle( file );
        delete [] dwpBits;
    }
    HDC getDC() const     { return hdc; }
    int getWidth() const  { return width; }
    int getHeight() const { return height; }
private:
    void createPen() {
        if( pen ) DeleteObject( pen );
        pen = CreatePen( PS_SOLID, wid, clr );
        SelectObject( hdc, pen );
    }
    HBITMAP bmp; HDC    hdc;
    HPEN    pen; HBRUSH brush;
    void    *pBits; int    width, height, wid;
    DWORD    clr;
};
class tree {
public:
    tree() {
        bmp.create( BMP_SIZE, BMP_SIZE ); bmp.clear();
        clr[0] = RGB( 90, 30, 0 );   clr[1] = RGB( 255, 255, 0 );
        clr[2] = RGB( 0, 255, 255 ); clr[3] = RGB( 255, 255, 255 );
        clr[4] = RGB( 255, 0, 0 );   clr[5] = RGB( 0, 100, 190 );
    }
    void draw( int it, POINT a, POINT b ) {
        if( !it ) return;
        bmp.setPenColor( clr[it % 6] );
        POINT df = { b.x - a.x, a.y -  b.y }; POINT c = { b.x - df.y, b.y - df.x };
        POINT d = { a.x - df.y, a.y - df.x };
        POINT e = { d.x + ( ( df.x - df.y ) / 2 ), d.y - ( ( df.x + df.y ) / 2 )};
        drawSqr( a, b, c, d ); draw( it - 1, d, e ); draw( it - 1, e, c );
    }
    void save( std::string p ) { bmp.saveBitmap( p ); }
private:
    void drawSqr( POINT a, POINT b, POINT c, POINT d ) {
        HDC dc = bmp.getDC();
        MoveToEx( dc, a.x, a.y, NULL );
        LineTo( dc, b.x, b.y );
        LineTo( dc, c.x, c.y );
        LineTo( dc, d.x, d.y );
        LineTo( dc, a.x, a.y );
    }
    myBitmap bmp;
    DWORD clr[6];
};
int main( int argc, char* argv[] ) {
    POINT ptA = { ( BMP_SIZE >> 1 ) - ( LINE_LEN >> 1 ), BMP_SIZE - BORDER },
          ptB = { ptA.x + LINE_LEN, ptA.y };
    tree t; t.draw( 12, ptA, ptB );
    // change this path 
    t.save( "?:/pt.bmp" );
    return 0;
}

Dart

Creating an SVG file

Translation of: Rust

Dart version: ^3.0.0

import 'dart:math';
import 'dart:io';

void main() {
  var basis = [(Point(-200.0, 0.0), Point(200.0, 0.0))];
  final groups = Iterable.generate(12, (lvl) {
    final basis0 = basis;
    basis = [];
    final lvlPolygons = basis0.map((pp) {
      final (a, b) = pp;
      final v =  Point((b - a).y, (a - b).x);
      final [c, d, e] = [a, b, (a + b + v) * 0.5].map((p) => p + v).toList();
      basis.addAll([(c, e), (e, d)]);
      return '<polygon points="${[a, c, e, d, c, d, b].expand((p) => [p.x, p.y]).join(' ')}"/>';
    }).join('\n');
    rg(int step) => ((80 + (lvl - 2) * step) & 255).toRadixString(16).padLeft(2, '0');
    return '<g fill="#${rg(20)}${rg(30)}18">\n$lvlPolygons\n</g>';
  }).join('\n');
  final (x, y) = basis.fold((0.0, 0.0), (p, pp) => (min(p.$1, pp.$1.x), min(p.$2, pp.$1.y)));
  final attrs = 'viewBox="$x $y ${-x - x} ${-y}" stroke="white" xmlns="http://www.w3.org/2000/svg"';
  File('Pythagor_tree.svg').writeAsString('<svg $attrs>\n$groups\n</svg>');
}

Drawing in Flutter

View output / play with the code - online in DartPad

import 'package:flutter/material.dart';

void main() => runApp(FittedBox(
    child: CustomPaint(painter: TreePainter(), size: const Size(2400, 1600))));

class TreePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final stroke = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 0.9
      ..color = Colors.white;
    final fill = Paint()..style = PaintingStyle.fill;
    canvas.drawColor(Colors.white, BlendMode.src);

    const halfBase = Offset(200, 0);
    var basis = [(size.bottomCenter(-halfBase), size.bottomCenter(halfBase))];
    for (var lvl = 0; lvl < 12; lvl++) {
      final path = Path();
      final basis0 = basis;
      basis = [];
      for (var (a, b) in basis0) {
        final v = Offset((b - a).dy, (a - b).dx);
        final [c, d, e] = [a, b, (a + b + v) / 2].map((p) => p + v).toList();
        basis.addAll([(c, e), (e, d)]);
        path.addPolygon([a, c, e, d, c, d, b], true);
      }
      rg(int step) => (80 + (lvl - 2) * step) & 255;
      canvas
        ..drawPath(path, fill..color = Color.fromARGB(255, rg(20), rg(30), 18))
        ..drawPath(path, stroke);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

EasyLang

Run it

proc tree x1 y1 x2 y2 depth . .
   if depth < 8
      dx = x2 - x1
      dy = y1 - y2
      x3 = x2 + dy
      y3 = y2 + dx
      x4 = x1 + dy
      y4 = y1 + dx
      x5 = x4 + 0.5 * (dx + dy)
      y5 = y4 + 0.5 * (dx - dy)
      color3 0.3 0.2 + depth / 18 0.1
      polygon [ x1 y1 x2 y2 x3 y3 x4 y4 ]
      polygon [ x3 y3 x4 y4 x5 y5 ]
      tree x4 y4 x5 y5 depth + 1
      tree x5 y5 x3 y3 depth + 1
   .
.
tree 41 10 59 10 0

F#

Creating an HTML file with an inline SVG. The generation of the tree is done breadth first.

type Point = { x:float; y:float }
type Line = { left : Point; right : Point }

let draw_start_html = """<!DOCTYPE html>
<html><head><title>Phytagoras tree</title>
<style type="text/css">polygon{fill:none;stroke:black;stroke-width:1}</style>
</head><body>
<svg width="640" height="640">"""

let draw_end_html = """Sorry, your browser does not support inline SVG.
</svg></body></html>"""

let svg_square x1 y1 x2 y2 x3 y3 x4 y4 =
    sprintf """<polygon points="%i %i %i %i %i %i %i %i" />"""
        (int x1) (int y1) (int x2) (int y2) (int x3) (int y3) (int x4) (int y4)

let out (x : string) = System.Console.WriteLine(x)

let sprout line =
    let dx = line.right.x - line.left.x
    let dy = line.left.y - line.right.y
    let line2 = {
        left = { x = line.left.x - dy; y = line.left.y - dx };
        right = { x = line.right.x - dy ; y = line.right.y - dx }
    }
    let triangleTop = {
        x = line2.left.x + (dx - dy) / 2.;
        y = line2.left.y - (dx + dy) / 2.
    }
    [
        { left = line2.left; right = triangleTop }
        { left = triangleTop; right = line2.right }
    ]
    
let draw_square line =
    let dx = line.right.x - line.left.x
    let dy = line.left.y - line.right.y
    svg_square line.left.x line.left.y line.right.x line.right.y
               (line.right.x - dy) (line.right.y - dx) (line.left.x - dy) (line.left.y - dx)

let rec generate lines = function
| 0 -> ()
| n ->
    let next =
        lines
        |> List.collect (fun line ->
            (draw_square >> out) line
            sprout line
        )
    generate next (n-1)


[<EntryPoint>]
let main argv =
    let depth = 1 + if argv.Length > 0 then (System.UInt32.Parse >> int) argv.[0] else 2
    out draw_start_html
    generate [{ left = { x = 275.; y = 500. }; right = { x = 375.; y = 500. } }] depth
    out draw_end_html
    0

FreeBASIC

Translation of: zkl
' version 03-12-2016
' compile with: fbc -s gui 
' or fbc -s console

Sub pythagoras_tree(x1 As Double, y1 As Double, x2 As Double, y2 As Double, depth As ULong)

    If depth > 10 Then Return

    Dim As Double dx = x2 - x1, dy = y1 - y2
    Dim As Double x3 = x2 - dy, y3 = y2 - dx
    Dim As Double x4 = x1 - dy, y4 = y1 - dx
    Dim As Double x5 = x4 + (dx - dy) / 2
    Dim As Double y5 = y4 - (dx + dy) / 2
    'draw the box
    Line (x1, y1) - (x2, y2) : Line - (x3, y3)
    Line - (x4, y4) : Line - (x1, y1)

    pythagoras_tree(x4, y4, x5, y5, depth +1)
    pythagoras_tree(x5, y5, x3, y3, depth +1)

End Sub

' ------=< MAIN >=------
' max for w is about max screensize - 500
Dim As ULong w = 800, h = w * 11 \ 16
Dim As ULong w2 = w \ 2, diff = w \ 12

ScreenRes w, h, 8
pythagoras_tree(w2 - diff, h -10 , w2 + diff , h -10 , 0)
' BSave "pythagoras_tree.bmp",0



' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

FutureBasic

_window = 1

void local fn BuildWindow
  CGRect r = fn CGRectMake( 0, 0, 705, 500 )
  window _window, @"Pythagoras Tree In FutureBasic", r, NSWindowStyleMaskTitled
  WindowSetBackgroundColor( _window, fn ColorBlack )
end fn

local fn PythagorasTree( x1 as double, y1 as double, x2 as double, y2 as double, depth as NSUInteger )
  if depth > 10 then exit fn
  
  double dx = x2 - x1, dy = y1 - y2
  double x3 = x2 - dy, y3 = y2 - dx
  double x4 = x1 - dy, y4 = y1 - dx
  double x5 = x4 + (dx - dy) / 2
  double y5 = y4 - (dx + dy) / 2
  
  select ( rnd(5) )
    case 1 : pen 2, fn ColorBrown
    case 2 : pen 2, fn ColorRed
    case 3 : pen 2, fn ColorOrange
    case 4 : pen 2, fn ColorYellow
    case 5 : pen 2, fn ColorGreen
  end select
  
  line x1, y1, x2, y2 : Line x2, y2, x3, y3
  line x3, y3, x4, y4 : Line x4, y4, x1, y1
  
  fn PythagorasTree( x4, y4, x5, y5, depth +1 )
  fn PythagorasTree( x5, y5, x3, y3, depth +1 )
end fn

local fn DrawTree
  NSUInteger  w = 700, h = w * 11 \ 16
  NSUInteger w2 = w \ 2, diff = w \ 12
  
  fn PythagorasTree( w2 - diff, h -10 , w2 + diff , h -10 , 0 )
end fn

random

fn BuildWindow
fn DrawTree

HandleEvents
Output:

Go

package main

import (
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"log"
	"os"
)

const (
	width, height = 800, 600
	maxDepth      = 11                    // how far to recurse, between 1 and 20 is reasonable
	colFactor     = uint8(255 / maxDepth) // adjusts the colour so leaves get greener further out
	fileName      = "pythagorasTree.png"
)

func main() {
	img := image.NewNRGBA(image.Rect(0, 0, width, height)) // create new image
	bg := image.NewUniform(color.RGBA{255, 255, 255, 255}) // prepare white for background
	draw.Draw(img, img.Bounds(), bg, image.ZP, draw.Src)   // fill the background

	drawSquares(340, 550, 460, 550, img, 0) // start off near the bottom of the image

	imgFile, err := os.Create(fileName)
	if err != nil {
		log.Fatal(err)
	}
	defer imgFile.Close()
	if err := png.Encode(imgFile, img); err != nil {
		imgFile.Close()
		log.Fatal(err)
	}
}

func drawSquares(ax, ay, bx, by int, img *image.NRGBA, depth int) {
	if depth > maxDepth {
		return
	}
	dx, dy := bx-ax, ay-by
	x3, y3 := bx-dy, by-dx
	x4, y4 := ax-dy, ay-dx
	x5, y5 := x4+(dx-dy)/2, y4-(dx+dy)/2
	col := color.RGBA{0, uint8(depth) * colFactor, 0, 255}
	drawLine(ax, ay, bx, by, img, col)
	drawLine(bx, by, x3, y3, img, col)
	drawLine(x3, y3, x4, y4, img, col)
	drawLine(x4, y4, ax, ay, img, col)
	drawSquares(x4, y4, x5, y5, img, depth+1)
	drawSquares(x5, y5, x3, y3, img, depth+1)
}

func drawLine(x0, y0, x1, y1 int, img *image.NRGBA, col color.RGBA) {
	dx := abs(x1 - x0)
	dy := abs(y1 - y0)
	var sx, sy int = -1, -1
	if x0 < x1 {
		sx = 1
	}
	if y0 < y1 {
		sy = 1
	}
	err := dx - dy
	for {
		img.Set(x0, y0, col)
		if x0 == x1 && y0 == y1 {
			break
		}
		e2 := 2 * err
		if e2 > -dy {
			err -= dy
			x0 += sx
		}
		if e2 < dx {
			err += dx
			y0 += sy
		}
	}
}
func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

Haskell

Haskell allows us to make highly modular solution.

Firstly, we define a function mkBranches that produces a pair of minor squares based on a given square. Each square is represented as a list of points.

mkBranches :: [(Float,Float)] -> [[(Float,Float)]]
mkBranches [a, b, c, d] = let d  = 0.5 <*> (b <+> (-1 <*> a))
                              l1 = d <+> orth d
                              l2 = orth l1
                    in
                      [ [a <+> l2, b <+> (2 <*> l2), a <+> l1, a]
                      , [a <+> (2 <*> l1), b <+> l1, b, b <+> l2] ]
  where
    (a, b) <+> (c, d) = (a+c, b+d)
    n <*> (a, b) = (a*n, b*n)
    orth (a, b) = (-b, a)

We then create squares using mkBranches to build a list representing the set of squares. In order to apply this function iteratively to form a 10-generation tree, we also have to define the monadic iteration iterateM within squares.

squares = concat $ take 10 $ iterateM mkBranches start
  where start = [(0,100),(100,100),(100,0),(0,0)]
        iterateM f x = iterate (>>= f) (pure x)

The raw result returned by squares should be used in the main function in order to be displayed in a new window, saved directly to a SVG file, or printed to a bitmap file.

Window output

Library: Gloss
--import should go to the top of the code
import Graphics.Gloss

main = display (InWindow "Pithagoras tree" (400, 400) (0, 0)) white tree
  where tree = foldMap lineLoop squares

SVG file

main = writeFile "pith.svg" svg
  where svg = "<svg " ++ attrs ++ foldMap (mkLine . close) squares ++ "</svg>"
        attrs = "fill='none' stroke='black' height='400' width='600'>"
        mkLine path = "<polyline points ='" ++ foldMap mkPoint path ++ "'/>"
        mkPoint (x,y) = show (250+x) ++ "," ++ show (400-y) ++ " "
        close lst = lst ++ [head lst]

Bitmap image

Library: easyplot
--import should go to the top of the code
import Graphics.EasyPlot

--change PNG by the desired format
main = plot (PNG "pith.png") $ map (mkLine . close) squares
  where mkLine = Data2D [Style Lines, Color Black,Title ""] []
        close lst = lst ++ [head lst]

J

require'plot'

Pt=: {{
  if. 0<m do.
    d=. 0j1*y-x
    p2=. y+d
    p3=. x+d
    p4=. (0.5*x+y)+1.5*d
    pd x,y,p2,p3
    p3 (<:m) Pt p4
    p4 (<:m) Pt p2
  end.
}}


Pytree=: {{
  pd 'reset'
  pd 'type poly'
  5r2j4 y Pt 7r2j4
  pd 'show'
}}

Pytree 7

Java

Works with: Java version 8
import java.awt.*;
import java.awt.geom.Path2D;
import javax.swing.*;

public class PythagorasTree extends JPanel {
    final int depthLimit = 7;
    float hue = 0.15f;

    public PythagorasTree() {
        setPreferredSize(new Dimension(640, 640));
        setBackground(Color.white);
    }

    private void drawTree(Graphics2D g, float x1, float y1, float x2, float y2,
            int depth) {

        if (depth == depthLimit)
            return;

        float dx = x2 - x1;
        float dy = y1 - y2;

        float x3 = x2 - dy;
        float y3 = y2 - dx;
        float x4 = x1 - dy;
        float y4 = y1 - dx;
        float x5 = x4 + 0.5F * (dx - dy);
        float y5 = y4 - 0.5F * (dx + dy);

        Path2D square = new Path2D.Float();
        square.moveTo(x1, y1);
        square.lineTo(x2, y2);
        square.lineTo(x3, y3);
        square.lineTo(x4, y4);
        square.closePath();

        g.setColor(Color.getHSBColor(hue + depth * 0.02f, 1, 1));
        g.fill(square);
        g.setColor(Color.lightGray);
        g.draw(square);

        Path2D triangle = new Path2D.Float();
        triangle.moveTo(x3, y3);
        triangle.lineTo(x4, y4);
        triangle.lineTo(x5, y5);
        triangle.closePath();

        g.setColor(Color.getHSBColor(hue + depth * 0.035f, 1, 1));
        g.fill(triangle);
        g.setColor(Color.lightGray);
        g.draw(triangle);

        drawTree(g, x4, y4, x5, y5, depth + 1);
        drawTree(g, x5, y5, x3, y3, depth + 1);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        drawTree((Graphics2D) g, 275, 500, 375, 500, 0);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setTitle("Pythagoras Tree");
            f.setResizable(false);
            f.add(new PythagorasTree(), BorderLayout.CENTER);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}

JavaScript

Translation of: Java

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <style>
        canvas {
            position: absolute;
            top: 45%;
            left: 50%;
            width: 640px;
            height: 640px;
            margin: -320px 0 0 -320px;
        }
    </style>
</head>

<body>
    <canvas></canvas>
    <script>
        'use strict';
        var canvas = document.querySelector('canvas');
        canvas.width = 640;
        canvas.height = 640;

        var g = canvas.getContext('2d');

        var depthLimit = 7;
        var hue = 0.15;

        function drawTree(x1, y1, x2, y2, depth) {

            if (depth == depthLimit)
                return;

            var dx = x2 - x1;
            var dy = y1 - y2;

            var x3 = x2 - dy;
            var y3 = y2 - dx;
            var x4 = x1 - dy;
            var y4 = y1 - dx;
            var x5 = x4 + 0.5 * (dx - dy);
            var y5 = y4 - 0.5 * (dx + dy);

            g.beginPath();
            g.moveTo(x1, y1);
            g.lineTo(x2, y2);
            g.lineTo(x3, y3);
            g.lineTo(x4, y4);
            g.closePath();

            g.fillStyle = HSVtoRGB(hue + depth * 0.02, 1, 1);
            g.fill();
            g.strokeStyle = "lightGray";
            g.stroke();

            g.beginPath();
            g.moveTo(x3, y3);
            g.lineTo(x4, y4);
            g.lineTo(x5, y5);
            g.closePath();

            g.fillStyle = HSVtoRGB(hue + depth * 0.035, 1, 1);
            g.fill();
            g.strokeStyle = "lightGray";
            g.stroke();

            drawTree(x4, y4, x5, y5, depth + 1);
            drawTree(x5, y5, x3, y3, depth + 1);
        }

        /* copied from stackoverflow */
        function HSVtoRGB(h, s, v) {
            var r, g, b, i, f, p, q, t;

            i = Math.floor(h * 6);
            f = h * 6 - i;
            p = v * (1 - s);
            q = v * (1 - f * s);
            t = v * (1 - (1 - f) * s);
            switch (i % 6) {
                case 0: r = v, g = t, b = p; break;
                case 1: r = q, g = v, b = p; break;
                case 2: r = p, g = v, b = t; break;
                case 3: r = p, g = q, b = v; break;
                case 4: r = t, g = p, b = v; break;
                case 5: r = v, g = p, b = q; break;
            }
            return "rgb("
                + Math.round(r * 255) + ","
                + Math.round(g * 255) + ","
                + Math.round(b * 255) + ")";
        }

        function draw() {
            g.clearRect(0, 0, canvas.width, canvas.height);
            drawTree(275, 500, 375, 500, 0);
        }
        draw();
    </script>

</body>

</html>

Translation of: Rust


Run this script from the browser console (F12) or from the <script> tag of an html document.

let base = [[{ x: -200, y: 0 }, { x: 200, y: 0 }]];
const doc = [...Array(12)].reduce((doc_a, _, lvl) => {
    const rg = step => `0${(80 + (lvl - 2) * step).toString(16)}`.slice(-2);
    return doc_a + base.splice(0).reduce((ga, [a, b]) => {
        const w = (kx, ky) => (kx * (b.x - a.x) + ky * (b.y - a.y)) / 2;
        const [c, e, d] = [2, 3, 2].map((j, i) => ({ x: a.x + w(i, j), y: a.y + w(-j, i) }));
        base.push([c, e], [e, d]);
        return ga + `<polygon points="${[a, c, e, d, c, d, b].map(p => [p.x, p.y])}"/>\n`;
    }, `<g fill="#${rg(20)}${rg(30)}18">\n`) + '</g>\n';
}, '<svg xmlns="http://www.w3.org/2000/svg" width="1200" stroke="white">\n') + '</svg>';

const { x, y } = base.flat().reduce((a, p) => ({ x: Math.min(a.x, p.x), y: Math.min(a.y, p.y) }));
const svg = doc.replace('<svg ', `<svg viewBox="${[x, y, -x - x, -y]}" `);
document.documentElement.innerHTML = svg, ''; // display svg in the browser window

jq

Adapted from Wren

Works with: jq

Works with gojq, the Go implementation of jq

The jq program presented here generates SVG, which can readily be viewed in a browser, at least if the file suffix is .svg.

Notice that the SVG viewBox dimensions are computed dynamically.

# viewBox = <min-x> <min-y> <width> <height>
# Input: {svg, minx, miny, maxx, maxy}
def svg:
  "<svg viewBox='\(.minx - 4|floor) \(.miny - 4 |floor) \(6 + .maxx - .minx|ceil) \(6 + .maxy - .miny|ceil)'",
  "     preserveAspectRatio='xMinYmin meet'",
  "     xmlns='http://www.w3.org/2000/svg' >",
  .svg,
  "</svg>";

def minmax($xy):
    .minx = ([.minx, $xy[0]]|min)
  | .miny = ([.miny, $xy[1]]|min)
  | .maxx = ([.maxx, $xy[0]]|max)
  | .maxy = ([.maxy, $xy[1]]|max) ;

# default values for $fill and $stroke are provided
def Polygon( $ary; $fill; $stroke):
  def rnd: 1000*.|round/1000;
  ($fill // "none") as $fill
  | ($stroke // "black") as $stroke
  | ($ary | map(rnd) | join(" ")) as $a
  | .svg += "\n<polygon points='\($a)' fill='\($fill)' stroke='\($stroke)' />"
  | minmax($ary | [ ([ .[ range(0;length;2)]] |min),  ([ .[range(1;length;2)]]|min) ] )
  | minmax($ary | [ ([ .[ range(0;length;2)]] |max),  ([ .[range(1;length;2)]]|max) ] ) ;


def Square($A; $B; $C; $D; $fill; $stroke):
  Polygon( $A + $B + $C + $D; $fill; $stroke);

def Triangle($A; $B; $C; $fill; $stroke):
  Polygon( $A + $B + $C; $fill; $stroke);

def PythagorasTree:

  def drawTree($x1; $y1; $x2; $y2; $depth):
    if $depth <= 0 then .
    else ($x2 - $x1) as $dx
         | ($y1 - $y2) as $dy
         | ($x2 - $dy) as $x3
	 | ($y2 - $dx) as $y3
         | ($x1 - $dy) as $x4
         | ($y1 - $dx)  as $y4
	 | ($x4 + 0.5 * ($dx - $dy)) as $x5
         | ($y4 - 0.5 * ($dx + $dy)) as $y5

         # draw a square
	 | "rgb(\(256 - $depth * 20), 0, 0)" as $col
         | Square([$x1, $y1]; [$x2, $y2]; [$x3, $y3] ;  [$x4, $y4] ; $col; "lightgray")

         # draw a triangle
         | "rgb( 128, \(256 - $depth * 20), 128)" as $col
         | Triangle([$x3, $y3]; [$x4, $y4];  [$x5, $y5];  $col; "lightgray")
         | drawTree($x4; $y4; $x5; $y5; $depth - 1)
         | drawTree($x5; $y5; $x3; $y3; $depth - 1)
    end ;

  {svg: "", minx: infinite, miny: infinite, maxx: -infinite, maxy: -infinite}
  | drawTree(275; 500; 375; 500; 7);

PythagorasTree | svg
Output:


Julia

Translation of: PARI/GP
using Gadfly
using DataFrames

const xarray = zeros(Float64, 80000)
const yarray = zeros(Float64, 80000)
const arraypos = ones(Int32,1)
const maxdepth = zeros(Int32, 1)


function addpoints(x1, y1, x2, y2)
    xarray[arraypos[1]] = x1 
    xarray[arraypos[1]+1] = x2
    yarray[arraypos[1]] = y1
    yarray[arraypos[1]+1] = y2
    arraypos[1] += 2
end


function pythtree(ax, ay, bx, by, depth)
    if(depth > maxdepth[1])
        return
    end
    dx=bx-ax; dy=ay-by;
    x3=bx-dy; y3=by-dx;
    x4=ax-dy; y4=ay-dx;
    x5=x4+(dx-dy)/2; y5=y4-(dx+dy)/2;
    addpoints(ax, ay, bx, by)
    addpoints(bx, by, x3, y3)
    addpoints(x3, y3, x4, y4)
    addpoints(x4, y4, ax, ay)
    pythtree(x4, y4, x5, y5, depth + 1)
    pythtree(x5, y5, x3, y3, depth + 1)
end


function pythagorastree(x1, y1, x2, y2, size, maxdep)
    maxdepth[1] = maxdep
    println("Pythagoras Tree, depth $(maxdepth[1]), size $size, starts at ($x1, $y1, $x2, $y2)");
    pythtree(x1, y1, x2, y2, 0);
    df = DataFrame(x=xarray[1:arraypos[1]-1], y=-yarray[1:arraypos[1]-1])
    plot(df, x=:x, y=:y, Geom.path(), Theme(default_color="green", point_size=0.4mm))
end

pythagorastree(275.,500.,375.,500.,640., 9)

Kotlin

Translation of: Java
// version 1.1.2

import java.awt.*
import java.awt.geom.Path2D
import javax.swing.*

class PythagorasTree : JPanel() {
    val depthLimit = 7
    val hue = 0.15f

    init {
        preferredSize = Dimension(640, 640)
        background = Color.white
    }

    private fun drawTree(g: Graphics2D, x1: Float, y1: Float,
                                        x2: Float, y2: Float, depth: Int) {
        if (depth == depthLimit) return

        val dx = x2 - x1
        val dy = y1 - y2

        val x3 = x2 - dy
        val y3 = y2 - dx
        val x4 = x1 - dy
        val y4 = y1 - dx
        val x5 = x4 + 0.5f * (dx - dy)
        val y5 = y4 - 0.5f * (dx + dy)

        val square = Path2D.Float()
        with (square) {
            moveTo(x1, y1)
            lineTo(x2, y2)
            lineTo(x3, y3)
            lineTo(x4, y4)
            closePath()
        }

        g.color = Color.getHSBColor(hue + depth * 0.02f, 1.0f, 1.0f)
        g.fill(square)
        g.color = Color.lightGray
        g.draw(square)

        val triangle = Path2D.Float()
        with (triangle) {
            moveTo(x3, y3)
            lineTo(x4, y4)
            lineTo(x5, y5)
            closePath()
        }

        g.color = Color.getHSBColor(hue + depth * 0.035f, 1.0f, 1.0f)
        g.fill(triangle)
        g.color = Color.lightGray
        g.draw(triangle)

        drawTree(g, x4, y4, x5, y5, depth + 1)
        drawTree(g, x5, y5, x3, y3, depth + 1)
    }

    override fun paintComponent(g: Graphics) {
        super.paintComponent(g)
        drawTree(g as Graphics2D, 275.0f, 500.0f, 375.0f, 500.0f, 0)
    }
}

fun main(args: Array<String>) {
    SwingUtilities.invokeLater {
        val f = JFrame()
        with (f) {
            defaultCloseOperation = JFrame.EXIT_ON_CLOSE
            title = "Pythagoras Tree"
            isResizable = false
            add(PythagorasTree(), BorderLayout.CENTER)
            pack()
            setLocationRelativeTo(null);
            setVisible(true)
        }
    }
}

M2000 Interpreter

Cartesian Coordinates

Translation of: zkl
MODULE Pythagoras_tree {
	CLS 5, 0  ' MAGENTA, NO SPLIT SCREEN
	PEN 14   ' YELLOW
	\\ code from zkl/Free Basic
	LET w = scale.x, h = w * 11 div 16
	LET w2 = w div 2, diff = w div 12
	LET TreeOrder = 6
	pythagoras_tree(w2 - diff, h -10, w2 + diff, h -10, 0)
	
	SUB pythagoras_tree(x1, y1, x2, y2, depth)
	 
	    IF depth > TreeOrder THEN EXIT SUB
	 
	    LOCAL dx = x2 - x1, dy = y1 - y2
	    LOCAL x3 = x2 - dy, y3 = y2 - dx
	    LOCAL x4 = x1 - dy, y4 = y1 - dx
	    LOCAL x5 = x4 + (dx - dy) / 2
	    LOCAL y5 = y4 - (dx + dy) / 2
	    MOVE x1, y1
	    DRAW TO x2, y2
	    DRAW TO x3, y3
	    DRAW TO x4, y4
	    DRAW TO x1, y1
	    pythagoras_tree(x4, y4, x5, y5, depth +1)
	    pythagoras_tree(x5, y5, x3, y3, depth +1)
	 
	END SUB
}
Pythagoras_tree

Polar Coordinates

MODULE Pythagoras_Example{
	CLS 5, 0  ' MAGENTA, split line = 0  
	PEN 14  ' YELLOW
	\\ Linux smoothing not work (we can use the statement but without effect)
	IF ISWINE ELSE SMOOTH ON
	\\ PYTHAGORAS TREE
	\\ by definition all variables ar type of a double
	GLOBAL p=7, p4=PI/4, p2=PI/2, s2=SQRT(2)/2
	MODULE center_p (r, t){
		MODULE pythagoras_tree (r, dx, depth) {
			r2=r-p2
			DRAW ANGLE r, dx
			DRAW ANGLE r2, dx
			DRAW ANGLE r, -dx
			DRAW ANGLE r2, -dx
			IF depth>10 THEN EXIT
			s3=dx*s2
			depth++
			STEP ANGLE r+p4, s3*2
			CALL pythagoras_tree r-p4,  s3, depth
			STEP ANGLE r, -dx-s3
			STEP ANGLE r, s3
			STEP ANGLE r+p4, -s3
			CALL pythagoras_tree r+p4,  s3, depth
			STEP ANGLE r-p4, s3		
		}	
		MOVE SCALE.X/2, SCALE.Y/2	
		STEP ANGLE PI-p4+r, t*s2
		CALL pythagoras_tree r, t, 1
	}
	r=PI/3
	pixels=100
	center_p r, 100*TWIPSX
	center_p r+PI, 100*TWIPSX
	CopyImageToClipboard()
	
	Sub CopyImageToClipboard()
		LOCAL Scr$=""
		MOVE 0,0
		COPY SCALE.X, SCALE.Y TO Scr$
		CLIPBOARD Scr$
	END SUB
}
Pythagoras_Example

Mathematica / Wolfram Language

n = 7;
colors = Blend[{Orange, Yellow, Green}, #] & /@ Subdivide[n - 1];
ClearAll[NextConfigs, NewConfig]
NewConfig[b1_List, b2_List] := Module[{diff, perp},
  diff = b2 - b1;
  perp = Cross[b2 - b1];
  <|"quad" -> Polygon[{b1, b2, b2 + perp, b1 + perp}], "triang" -> Polygon[{b1 + 1.5 perp + diff/2, b1 + perp, b2 + perp}]|>
  ]
NextConfigs[config_Association] := Module[{tr},
  tr = config["triangs"][[All, 1]];
  tr = Join[NewConfig @@@ tr[[All, {2, 1}]], NewConfig @@@ tr[[All, {1, 3}]]];
  <|"quads" -> tr[[All, "quad"]], "triangs" -> tr[[All, "triang"]]|>
  ]
nc = NewConfig[{-0.5, 0.0}, {0.5, 0.0}];
config = <|"quads" -> {nc["quad"]}, "triangs" -> {nc["triang"]}|>;
config = NestList[NextConfigs, config, n - 1];
Graphics[MapThread[{EdgeForm[Black], FaceForm[#2], #1["quads"], #1["triangs"]} &, {config, colors}]]

Nim

Translation of: Perl
Library: imageman

Using Perl algorithm with some changes: background is black and there is no color variation according to depth.

import imageman

const
  Width = 1920
  Height = 1080
  MaxDepth = 10
  Color = ColorRGBU([byte 0, 255, 0])


proc drawTree(img: var Image; x1, y1, x2, y2: int; depth: Natural) =

  if depth == 0: return

  let
    dx = x2 - x1
    dy = y1 - y2
    x3 = x2 - dy
    y3 = y2 - dx
    x4 = x1 - dy
    y4 = y1 - dx
    x5 = x4 + (dx - dy) div 2
    y5 = y4 - (dx + dy) div 2

  # Draw square.
  img.drawPolyline(true, Color, (x1, y1), (x2, y2), (x3, y3), (x4, y4))

  # Draw triangle.
  img.drawPolyline(true, Color, (x3, y3), (x4, y4), (x5, y5))

  # Next level.
  img.drawTree(x4, y4, x5, y5, depth - 1)
  img.drawTree(x5, y5, x3, y3, depth - 1)


var image = initImage[ColorRGBU](Width, Height)
image.drawTree(int(Width / 2.3), Height - 1, int(Width / 1.8), Height - 1, MaxDepth)
image.savePNG("pythagoras_tree.png", compression = 9)

Ol

(import (lib gl))
(import (OpenGL version-1-0))
(gl:set-window-size 700 600)
(gl:set-window-title "http://rosettacode.org/wiki/Pythagoras_tree")

(glLineWidth 2)
(gl:set-renderer (lambda (mouse)
   (glClear GL_COLOR_BUFFER_BIT)
   (glLoadIdentity)
   (glOrtho -3 4 -1 5 0 1)

   (let loop ((a '(0 . 0)) (b '(1 . 0)) (n 7))
      (unless (zero? n)
         (define dx (- (car b) (car a)))
         (define dy (- (cdr b) (cdr a)))
         (define c (cons
            (- (car b) dy)
            (+ (cdr b) dx)))
         (define d (cons
            (- (car a) dy)
            (+ (cdr a) dx)))
         (define e (cons
            (- (/ (+ (car c) (car d)) 2) (/ dy 2))
            (+ (/ (+ (cdr c) (cdr d)) 2) (/ dx 2))))

         (glColor3f 0 (+ 1/3 (/ 2/3 n)) 0)
         (glBegin GL_QUADS)
            (glVertex2f (car a) (cdr a))
            (glVertex2f (car b) (cdr b))
            (glVertex2f (car c) (cdr c))
            (glVertex2f (car d) (cdr d))
         (glEnd)
         (glColor3f 1 0 0)
         (glBegin GL_TRIANGLES)
            (glVertex2f (car c) (cdr c))
            (glVertex2f (car e) (cdr e))
            (glVertex2f (car d) (cdr d))
         (glEnd)
         (loop d e (- n 1))
         (loop e c (- n 1))
      ))
))

PARI/GP

Output PythTree1.png

This version with recursion, in general, is a translation of zkl version. Almost "as is", so, outputting upside-down tree.

Translation of: zkl
Works with: PARI/GP version 2.7.4 and above
\\ Pythagoras Tree (w/recursion)
\\ 4/11/16 aev
plotline(x1,y1,x2,y2)={plotmove(0, x1,y1);plotrline(0,x2-x1,y2-y1);}

pythtree(ax,ay,bx,by,d=0)={
my(dx,dy,x3,y3,x4,y4,x5,y5);
if(d>10, return());
dx=bx-ax; dy=ay-by;
x3=bx-dy; y3=by-dx;
x4=ax-dy; y4=ay-dx;
x5=x4+(dx-dy)\2; y5=y4-(dx+dy)\2;
plotline(ax,ay,bx,by);
plotline(bx,by,x3,y3);
plotline(x3,y3,x4,y4);
plotline(x4,y4,ax,ay);
pythtree(x4,y4,x5,y5,d+1);
pythtree(x5,y5,x3,y3,d+1);
}

PythagorTree(x1,y1,x2,y2,depth=9,size)={
my(dx=1,dy=0,ttlb="Pythagoras Tree, depth ",ttl=Str(ttlb,depth));
print1(" *** ",ttl); print(", size ",size);
print(" *** Start: ",x1,",",y1,",",x2,",",y2);
plotinit(0);
plotcolor(0,6); \\green
plotscale(0, -size,size, size,0 ); 
plotmove(0, 0,0);
pythtree(x1,y1, x2,y2);
plotdraw([0,size,size]);
}

{\\ Executing:
PythagorTree(275,500,375,500,9,640);    \\PythTree1.png
}
Output:
 *** Pythagoras Tree, depth 9, size 640
 *** Start: 275,500,375,500

Perl

Translation of: Sidef
use Imager;

sub tree {
    my ($img, $x1, $y1, $x2, $y2, $depth) = @_;

    return () if $depth <= 0;

    my $dx = ($x2 - $x1);
    my $dy = ($y1 - $y2);

    my $x3 = ($x2 - $dy);
    my $y3 = ($y2 - $dx);
    my $x4 = ($x1 - $dy);
    my $y4 = ($y1 - $dx);
    my $x5 = ($x4 + 0.5 * ($dx - $dy));
    my $y5 = ($y4 - 0.5 * ($dx + $dy));

    # Square
    $img->polygon(
        points => [
            [$x1, $y1],
            [$x2, $y2],
            [$x3, $y3],
            [$x4, $y4],
        ],
        color => [0, 255 / $depth, 0],
    );

    # Triangle
    $img->polygon(
        points => [
            [$x3, $y3],
            [$x4, $y4],
            [$x5, $y5],
        ],
        color => [0, 255 / $depth, 0],
    );

    tree($img, $x4, $y4, $x5, $y5, $depth - 1);
    tree($img, $x5, $y5, $x3, $y3, $depth - 1);
}

my ($width, $height) = (1920, 1080);
my $img = Imager->new(xsize => $width, ysize => $height);
$img->box(filled => 1, color => 'white');
tree($img, $width/2.3, $height, $width/1.8, $height, 10);
$img->write(file => 'pythagoras_tree.png');

Phix

Translation of: Java
Library: Phix/pGUI
Library: Phix/online

You can run this online here.

-- demo\rosetta\PythagorasTree.exw
with javascript_semantics
include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

enum FILL, BORDER

procedure drawTree(atom x1, y1, x2, y2, integer depth, dd)
    atom dx = x2 - x1,
         dy = y1 - y2,
         x3 = x2 - dy,
         y3 = y2 - dx,
         x4 = x1 - dy,
         y4 = y1 - dx,
         x5 = x4 + 0.5 * (dx - dy),
         y5 = y4 - 0.5 * (dx + dy)
 
    if depth=dd then
        integer r = 250-depth*20

        for draw=FILL to BORDER do
            -- one square... 
            cdCanvasSetForeground(cddbuffer, iff(draw=FILL?rgb(r,#FF,0):CD_GRAY))
            integer mode = iff(draw=FILL?CD_FILL:CD_CLOSED_LINES)
            cdCanvasBegin(cddbuffer,mode)
            cdCanvasVertex(cddbuffer, x1, 640-y1)
            cdCanvasVertex(cddbuffer, x2, 640-y2)
            cdCanvasVertex(cddbuffer, x3, 640-y3)
            cdCanvasVertex(cddbuffer, x4, 640-y4)
            cdCanvasEnd(cddbuffer)
            -- ...and the attached triangle
            if draw=FILL then 
                cdCanvasSetForeground(cddbuffer, rgb(r-depth*10,#FF,0))
            end if
            cdCanvasBegin(cddbuffer,mode)
            cdCanvasVertex(cddbuffer, x3, 640-y3)
            cdCanvasVertex(cddbuffer, x4, 640-y4)
            cdCanvasVertex(cddbuffer, x5, 640-y5)
            cdCanvasEnd(cddbuffer)
        end for
    elsif depth<dd then
        drawTree(x4, y4, x5, y5, depth + 1, dd)
        drawTree(x5, y5, x3, y3, depth + 1, dd)
    end if
end procedure

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
    cdCanvasActivate(cddbuffer)
    for i=0 to 7 do -- (draw leaves last)
        drawTree(275, 500, 375, 500, 0, i)
    end for
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_WHITE)
    cdCanvasSetForeground(cddbuffer, CD_RED)
    return IUP_DEFAULT
end function

procedure main()
    IupOpen()

    canvas = IupCanvas(NULL)
    IupSetAttribute(canvas, "RASTERSIZE", "640x640")
    IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
    IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))

    dlg = IupDialog(canvas,"RESIZE=NO")
    IupSetAttribute(dlg, "TITLE", "Pythagoras Tree")

    IupShow(dlg)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()

Processing

Translation of: Sidef
void tree(float x1, float y1, float x2, float y2, int depth) {

  if (depth <= 0) {
    return;
  }

  float dx = (x2 - x1);
  float dy = (y1 - y2);

  float x3 = (x2 - dy);
  float y3 = (y2 - dx);
  float x4 = (x1 - dy);
  float y4 = (y1 - dx);
  float x5 = (x4 + 0.5*(dx - dy));
  float y5 = (y4 - 0.5*(dx + dy));

  // square
  beginShape();
  fill(0.0, 255.0/depth, 0.0);
  vertex(x1, y1);
  vertex(x2, y2);
  vertex(x3, y3);
  vertex(x4, y4);
  vertex(x1, y1);
  endShape();

  // triangle
  beginShape();
  fill(0.0, 255.0/depth, 0.0);
  vertex(x3, y3);
  vertex(x4, y4);
  vertex(x5, y5);
  vertex(x3, y3);
  endShape();

  tree(x4, y4, x5, y5, depth-1);
  tree(x5, y5, x3, y3, depth-1);
}  

void setup() {
  size(1920, 1080);
  background(255);
  stroke(0, 255, 0);
  tree(width/2.3, height, width/1.8, height, 10);
}

Processing Python mode

def setup():
    size(800, 400)
    background(255)
    stroke(0, 255, 0)
    tree(width / 2.3, height, width / 1.8, height, 10)


def tree(x1, y1, x2, y2, depth):
    if depth <= 0: return
    dx = (x2 - x1)
    dy = (y1 - y2)

    x3 = (x2 - dy)
    y3 = (y2 - dx)
    x4 = (x1 - dy)
    y4 = (y1 - dx)
    x5 = (x4 + 0.5 * (dx - dy))
    y5 = (y4 - 0.5 * (dx + dy))

    # square
    beginShape()
    fill(0.0, 255.0 / depth, 0.0)
    vertex(x1, y1)
    vertex(x2, y2)
    vertex(x3, y3)
    vertex(x4, y4)
    vertex(x1, y1)
    endShape()

    # triangle
    beginShape()
    fill(0.0, 255.0 / depth, 0.0)
    vertex(x3, y3)
    vertex(x4, y4)
    vertex(x5, y5)
    vertex(x3, y3)
    endShape()

    tree(x4, y4, x5, y5, depth - 1)
    tree(x5, y5, x3, y3, depth - 1)

PureBasic

Translation of: FreeBasic
EnableExplicit
DisableDebugger

Procedure.d maxXY(a.d,b.d,c.d,d.d)
  If a<b : Swap a,b : EndIf
  If a<c : Swap a,c : EndIf
  If a<d : Swap a,d : EndIf  
  ProcedureReturn a
EndProcedure

Procedure.d minXY(a.d,b.d,c.d,d.d)
  If a>b : Swap a,b : EndIf
  If a>c : Swap a,c : EndIf
  If a>d : Swap a,d : EndIf  
  ProcedureReturn a
EndProcedure

Procedure Ptree(x1.d, y1.d, x2.d, y2.d, d.i=0)
  If d>10 : ProcedureReturn : EndIf
  
  Define dx.d=x2-x1,
         dy.d=y1-y2,
         x3.d=x2-dy,
         y3.d=y2-dx,
         x4.d=x1-dy,
         y4.d=y1-dx,
         x5.d=x4+(dx-dy)/2.0,
         y5.d=y4-(dx+dy)/2.0,
         p1.d=(maxXY(x1,x2,x3,x4)+minXY(x1,x2,x3,x4))/2.0,
         p2.d=(maxXY(y1,y2,y3,y4)+minXY(y1,y2,y3,y4))/2.0,
         p3.d=(maxXY(x1,x2,x3,x4)-minXY(x1,x2,x3,x4))        
    
  FrontColor(RGB(Random(125,1),Random(255,125),Random(125,1)))    
  LineXY(x1,y1,x2,y2)
  LineXY(x2,y2,x3,y3)
  LineXY(x3,y3,x4,y4)
  LineXY(x4,y4,x1,y1)
  BoxedGradient(minXY(x1,x2,x3,x4),minXY(y1,y2,y3,y4),p3,p3)
  FillArea(p1,p2,-1)
  
  Ptree(x4,y4,x5,y5,d+1)
  Ptree(x5,y5,x3,y3,d+1)
  
EndProcedure

Define w1.i=800,
       h1.i=w1*11/16,
       w2.i=w1/2,
       di.i=w1/12

If OpenWindow(0,#PB_Ignore,#PB_Ignore,w1,h1,"Pythagoras tree")
  If CreateImage(0,w1,h1,24,0) And StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Gradient)
    BackColor($000000)
    Ptree(w2-di,h1-10,w2+di,h1-10)    
    StopDrawing()
  EndIf
  ImageGadget(0,0,0,0,0,ImageID(0))  
  Repeat : Until WaitWindowEvent(50)=#PB_Event_CloseWindow
EndIf
End

Python

Using turtle graphics and the Zkl example for the calculations.

from turtle import goto, pu, pd, color, done

def level(ax, ay, bx, by, depth=0):
    if depth > 0:
        dx,dy = bx-ax, ay-by
        x3,y3 = bx-dy, by-dx
        x4,y4 = ax-dy, ay-dx
        x5,y5 = x4 + (dx - dy)/2, y4 - (dx + dy)/2
        goto(ax, ay), pd()
        for x, y in ((bx, by), (x3, y3), (x4, y4), (ax, ay)):
            goto(x, y)
        pu()
        level(x4,y4, x5,y5, depth - 1)
        level(x5,y5, x3,y3, depth - 1)

if __name__ == '__main__':
    color('red', 'yellow')
    pu()
    level(-100, 500, 100, 500, depth=8)
    done()

R

Translation of: PARI/GP
Works with: R version 3.3.3 and above
File:PYTHTR9.png
Output PYTHTR9.png
File:PYTHTR7.png
Output PYTHTR7.png
## Recursive PT plotting
pythtree <- function(ax,ay,bx,by,d) {
  if(d<0) {return()}; clr="darkgreen";
  dx=bx-ax; dy=ay-by;
  x3=bx-dy; y3=by-dx;
  x4=ax-dy; y4=ay-dx;
  x5=x4+(dx-dy)/2; y5=y4-(dx+dy)/2;
  segments(ax,-ay,bx,-by, col=clr);
  segments(bx,-by,x3,-y3, col=clr);
  segments(x3,-y3,x4,-y4, col=clr);
  segments(x4,-y4,ax,-ay, col=clr);
  pythtree(x4,y4,x5,y5,d-1);
  pythtree(x5,y5,x3,y3,d-1);
}
## Plotting Pythagoras Tree. aev 3/27/17
## x1,y1,x2,y2 - starting position
## ord - order/depth, fn - file name, ttl - plot title.
pPythagorasT <- function(x1, y1,x2, y2, ord, fn="", ttl="") {
  cat(" *** START PYTHT:", date(), "\n");
  m=640; i=j=k=m1=m-2; x=y=d=dm=0;
  if(fn=="") {pf=paste0("PYTHTR", ord, ".png")} else {pf=paste0(fn, ".png")};
  if(ttl=="") {ttl=paste0("Pythagoras tree, order - ", ord)};
  cat(" *** Plot file -", pf, "title:", ttl, "\n");
  plot(NA, xlim=c(0,m), ylim=c(-m,0), xlab="", ylab="", main=ttl);
  pythtree(x1,y1, x2,y2, ord);
  dev.copy(png, filename=pf, width=m, height=m);
  dev.off(); graphics.off();
  cat(" *** END PYTHT:",date(),"\n");
}
## Executing:
pPythagorasT(275,500,375,500,9) 
pPythagorasT(275,500,375,500,7)
Output:
> pPythagorasT(275,500,375,500,9) 
 *** START PYTHT: Tue Mar 28 15:57:19 2017 
 *** Plot file - PYTHTR9.png title: Pythagoras tree, order - 9 
 *** END PYTHT: Tue Mar 28 15:57:20 2017 
> pPythagorasT(275,500,375,500,7) 
 *** START PYTHT: Tue Mar 28 15:59:25 2017 
 *** Plot file - PYTHTR7.png title: Pythagoras tree, order - 7 
 *** END PYTHT: Tue Mar 28 15:59:25 2017

QB64

_Title "Pythagoras Tree"

Dim As Integer sw, sh
sw = 640
sh = 480

Screen _NewImage(sw, sh, 32)

Call pythTree(sw / 2 - sw / 12, sh - 30, sw / 2 + sw / 12, sh - 30, 0)

Sleep
System

Sub pythTree (ax As Integer, ay As Integer, bx As Integer, by As Integer, depth As Integer)
    Dim As Single cx, cy, dx, dy, ex, ey
    Dim As Integer c

    cx = ax - ay + by
    cy = ax + ay - bx
    dx = bx + by - ay
    dy = ax - bx + by
    ex = (cx - cy + dx + dy) * 0.5
    ey = (cx + cy - dx + dy) * 0.5
    c = depth * 15
    Color _RGB(c Mod 256, Abs((255 - c)) Mod 256, (144 + c) Mod 256)
    Line (cx, cy)-(ax, ay)
    Line (ax, ay)-(bx, by)
    Line (bx, by)-(dx, dy)
    Line (dx, dy)-(cx, cy)
    Line (cx, cy)-(ex, ey)
    Line (ex, ey)-(dx, dy)
    If depth < 12 Then
        Call pythTree(cx, cy, ex, ey, depth + 1)
        Call pythTree(ex, ey, dx, dy, depth + 1)
    End If
End Sub


Racket

#lang racket
(require racket/draw pict)

(define (draw-pythagoras-tree order x0 y0 x1 y1)
  (λ (the-dc dx dy)
    (define (inr order x0 y0 x1 y1)
      (when (positive? order)
        (let* ((y0-1 (- y0 y1))
               (x1-0 (- x1 x0))
               (x2 (+ x1 y0-1))
               (y2 (+ y1 x1-0))
               (x3 (+ x0 y0-1))
               (y3 (+ y0 x1-0))
               (x4 (+ x2 x3 (/ (+ x0 x2) -2)))
               (y4 (+ y2 y3 (/ (+ y0 y2) -2)))
               (path (new dc-path%)))
          (send* path [move-to x0 y0]
            [line-to x1 y1] [line-to x2 y2] [line-to x3 y3]
            [close])
          (send the-dc draw-path path dx dy)
          (inr (sub1 order) x3 y3 x4 y4)
          (inr (sub1 order) x4 y4 x2 y2))))
    
    (define old-brush (send the-dc get-brush))
    (define old-pen (send the-dc get-pen))
    (send the-dc set-pen (new pen% [width 1] [color "black"]))
    (inr (add1 order) x0 y0 x1 y1)
    (send the-dc set-brush old-brush)
    (send the-dc set-pen old-pen)))

(dc (draw-pythagoras-tree 7 (+ 200 32) 255 (- 200 32) 255) 400 256)

Raku

(formerly Perl 6) We'll generate a SVG image.

class Square {
    has Complex ($.position, $.edge);
    method size { $!edge.abs }
    method svg-polygon {
	qq[<polygon points="{join ' ', map
	{ ($!position + $_ * $!edge).reals.join(',') },
	0, 1, 1+1i, 1i}" style="fill:lime;stroke=black" />]
    }
    method left-child {
	self.new:
	position => $!position + i*$!edge,
	edge => sqrt(2)/2*cis(pi/4)*$!edge;
    }
    method right-child {
	self.new:
	position => $!position + i*$!edge + self.left-child.edge,
	edge => sqrt(2)/2*cis(-pi/4)*$!edge;
    }
}

BEGIN say '<svg width="500" height="500">';
END   say '</svg>';

sub tree(Square $s, $level = 0) {
    return if $level > 8;
    say $s.svg-polygon;
    tree($s.left-child, $level+1);
    tree($s.right-child, $level+1);
}

tree Square.new: :position(250+0i), :edge(60+0i);

Ring

# Project : Pythagoras tree

load "guilib.ring"

paint = null

new qapp 
        {
        win1 = new qwidget() {
                  setwindowtitle("Pythagoras tree")
                  setgeometry(100,100,800,600)
                  label1 = new qlabel(win1) {
                              setgeometry(10,10,800,600)
                              settext("")
                  }
                  new qpushbutton(win1) {
                          setgeometry(150,500,100,30)
                          settext("draw")
                          setclickevent("draw()")
                  }
                  show()
        }
        exec()
        }

func draw
        p1 = new qpicture()
               color = new qcolor() {
               setrgb(0,0,255,255)
        }
        pen = new qpen() {
                 setcolor(color)
                 setwidth(1)
        }
        paint = new qpainter() {
                  begin(p1)
                  setpen(pen)

        w = 800
        h = floor(w*11/16)
        w2 = floor(w/2)
        diff = floor(w/12)
 
        pythagorastree(w2 - diff,h -10,w2 + diff ,h -10 ,0)

        endpaint()
        }
        label1 { setpicture(p1) show() }
        return


func pythagorastree(x1,y1,x2,y2,depth) 
        if depth > 10 
           return
        ok 
        dx = x2 - x1
        dy = y1 - y2
        x3 = x2 - dy
        y3 = y2 - dx
        x4 = x1 - dy
        y4 = y1 - dx
        x5 = x4 + floor((dx - dy) / 2)
        y5 = y4 - floor((dx + dy) / 2)
        paint.drawline(x1,y1,x2,y2)
        paint.drawline(x2,y2,x3,y3)
        paint.drawline(x4,y4,x1,y1) 
        pythagorastree(x4, y4, x5, y5, depth +1)
        pythagorastree(x5, y5, x3, y3, depth +1)

Output: https://www.dropbox.com/s/a1gtue7tvmaj2je/PythagorasTree.jpg?dl=0

Ruby

Library: RubyGems
Library: JRubyArt

A clone of processing version

# frozen_string_literal: true

def setup
  sketch_title 'Pythagoras Tree'
  background(255)
  stroke(0, 255, 0)
  tree(width / 2.3, height, width / 1.8, height, 10)
end

def tree(x1, y1, x2, y2, depth)
  return if depth <= 0

  dx = (x2 - x1)
  dy = (y1 - y2)

  x3 = (x2 - dy)
  y3 = (y2 - dx)
  x4 = (x1 - dy)
  y4 = (y1 - dx)
  x5 = (x4 + 0.5 * (dx - dy))
  y5 = (y4 - 0.5 * (dx + dy))
  # square
  begin_shape
  fill(0.0, 255.0 / depth, 0.0)
  vertex(x1, y1)
  vertex(x2, y2)
  vertex(x3, y3)
  vertex(x4, y4)
  vertex(x1, y1)
  end_shape
  # triangle
  begin_shape
  fill(0.0, 255.0 / depth, 0.0)
  vertex(x3, y3)
  vertex(x4, y4)
  vertex(x5, y5)
  vertex(x3, y3)
  end_shape
  tree(x4, y4, x5, y5, depth - 1)
  tree(x5, y5, x3, y3, depth - 1)
end

def settings
  size(800, 400)
end

Rust

Creates a svg file (12 levels)

[dependencies]
svg = "0.12"

use svg::node::element::{Group, Polygon};

fn main() {
    let mut base: Vec<[(f64, f64); 2]> = vec![[(-200., 0.), (200., 0.)]];
    let doc = (0..12_u8).fold(svg::Document::new().set("stroke", "white"), |doc_a, lvl| {
        let rg = |step| lvl.wrapping_mul(step).wrapping_add(80 - step * 2);
        let g = Group::new().set("fill", format!("#{:02X}{:02X}18", rg(20), rg(30))); // level color
        doc_a.add(base.split_off(0).into_iter().fold(g, |ga, [a, b]| {
            let v = (b.0 - a.0, b.1 - a.1);
            let [c, d, w] = [a, b, v].map(|p| (p.0 + v.1, p.1 - v.0));
            let e = (c.0 + w.0 / 2., c.1 + w.1 / 2.);
            base.extend([[c, e], [e, d]]);
            ga.add(Polygon::new().set("points", vec![a, c, e, d, c, d, b]))
        }))
    });
    let (x, y) = (base.iter()).fold((0., 0.), |(xa, ya), [p, _]| (p.0.min(xa), p.1.min(ya)));
    svg::save("Pythagor_tree.svg", &doc.set("viewBox", (x, y, -x - x, -y))).unwrap();
}

Scala

Java Swing Interoperability

import java.awt._
import java.awt.geom.Path2D

import javax.swing.{JFrame, JPanel, SwingUtilities, WindowConstants}

object PythagorasTree extends App {

  SwingUtilities.invokeLater(() => {
    new JFrame {

      class PythagorasTree extends JPanel {
        setPreferredSize(new Dimension(640, 640))
        setBackground(Color.white)

        override def paintComponent(g: Graphics): Unit = {
          val (depthLimit, hue) = (7, 0.15f)

          def drawTree(g: Graphics2D, x1: Float, y1: Float, x2: Float, y2: Float, depth: Int): Unit = {
            if (depth == depthLimit) return
            val (dx, dy) = (x2 - x1, y1 - y2)
            val (x3, y3) = (x2 - dy, y2 - dx)
            val (x4, y4) = (x1 - dy, y1 - dx)
            val (x5, y5) = (x4 + 0.5F * (dx - dy), y4 - 0.5F * (dx + dy))
            val square = new Path2D.Float {
              moveTo(x1, y1); lineTo(x2, y2); lineTo(x3, y3); lineTo(x4, y4); closePath()
            }
            val triangle = new Path2D.Float {
              moveTo(x3, y3); lineTo(x4, y4); lineTo(x5, y5); closePath()
            }
            g.setColor(Color.getHSBColor(hue + depth * 0.02f, 1, 1))
            g.fill(square)
            g.setColor(Color.lightGray)
            g.draw(square)
            g.setColor(Color.getHSBColor(hue + depth * 0.035f, 1, 1))
            g.fill(triangle)
            g.setColor(Color.lightGray)
            g.draw(triangle)
            drawTree(g, x4, y4, x5, y5, depth + 1)
            drawTree(g, x5, y5, x3, y3, depth + 1)
          }

          super.paintComponent(g)
          drawTree(g.asInstanceOf[Graphics2D], 275, 500, 375, 500, 0)
        }
      }

      setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
      setTitle("Pythagoras Tree")
      setResizable(false)
      add(new PythagorasTree, BorderLayout.CENTER)
      pack()
      setLocationRelativeTo(null)
      setVisible(true)
    }
  })

}

Scilab

L-System approach

This solution uses complex numbers to represent vectors, and it draws the contour of the tree. By "uncommenting" the six commented lines inside the select structure, it will also draw the triangles between the squares. The output is a new graphic window.

side = 1;       //side length of the square
depth = 8;      //final number of branch levels

//L-system definition:
//Alphabet: UTDB+-[]
    //U: go upwards             T: top of the square
    //D: go downwards           B: bottom of the square
    //[: start new branch       ]: end current branch
    //+: branch to the right    -: branch to the left
//Axiom:    UTDB
//Rule:     T -> [+UTD-UTD]

//L-system sentence generation
sentence = 'UTDB'
rule = '[+UTD-UTD]';
for i=1:depth
    sentence = strsubst(sentence,'T',rule);
end
sentence = strsplit(sentence)';

//Empty tree
tree_size = 1.0...
            + length(find(sentence == "U" | sentence == "T" |...
                          sentence == "D" | sentence == "B"))...
            + 2 * length(find(sentence == "]" | sentence == "-" |...
                              sentence == "+"));
tree=zeros(tree_size,1);

//Vectorial operation to calculate a new point in the tree
deff('z = new_point(origin,rho,theta)',...
     'z = origin + rho * exp(%i*theta)');
     
//Drawing the tree
curr_angle = %pi/2;
curr_pos = 1;
ratio = 1/sqrt(2);
for ind = 1:size(sentence,'c')
    charac = sentence(ind);
    
    select charac
    case 'U' then //Draw line upwards
        tree(curr_pos+1) = new_point(tree(curr_pos),side,curr_angle);
        curr_pos = curr_pos + 1;
        
    case 'T' then //Draw top of the square
        curr_angle = curr_angle - %pi/2;
        tree(curr_pos+1) = new_point(tree(curr_pos),side,curr_angle);
        curr_pos = curr_pos + 1;
        
    case 'D' then //Draw line downwards
        curr_angle = curr_angle - %pi/2;
        tree(curr_pos+1) = new_point(tree(curr_pos),side,curr_angle);
        curr_pos = curr_pos + 1;
        
    case 'B' then //Draw the bottom
        curr_angle = curr_angle - %pi/2;
        tree(curr_pos+1) = new_point(tree(curr_pos),side,curr_angle);
        curr_pos = curr_pos + 1;
        
    case '[' then //Start branch
        side = side * ratio;
        
    case '+' then //Start going to the left
        curr_angle = curr_angle - %pi/4;
//        tree(curr_pos+1) = new_point(tree(curr_pos),side,curr_angle);
//        tree(curr_pos+2) = new_point(tree(curr_pos+1),side,%pi+curr_angle);
//        curr_pos = curr_pos + 2;
        curr_angle = curr_angle + %pi/2;
        
    case '-' then //Start going to the left
//        tree(curr_pos+1) = new_point(tree(curr_pos),side,curr_angle);
//        tree(curr_pos+2) = new_point(tree(curr_pos+1),side,%pi+curr_angle);
//        curr_pos = curr_pos + 2;
        curr_angle = curr_angle + %pi/2;
    case ']' then
        side = side / ratio;
        curr_angle = curr_angle - %pi/4;
//        tree(curr_pos+1) = new_point(tree(curr_pos),side,curr_angle);
//        tree(curr_pos+2) = new_point(tree(curr_pos+1),side,%pi+curr_angle);
//        curr_pos = curr_pos + 2;
        curr_angle = curr_angle + %pi;
        
    else
        error('L-system sentence error');
    end
end

scf(); clf();
xname('Pythagoras tree: '+string(depth)+' levels')
plot2d(real(tree),imag(tree),14);
set(gca(),'isoview','on');
set(gca(),'axes_visible',['off','off','off']);

Recursive approach

A minor change was made so that the final depth of the tree is an argument of fcn, and not a condition set within itself.

Translation of: zkl
function []=fcn(bitmap,ax,ay,bx,by,depth)
    if depth < 0 then
        return
    end
    
    dx = bx - ax; dy = ay - by;
    x3 = bx + dy; y3 = by + dx;
    x4 = ax + dy; y4 = ay + dx;
    x5 = x4 + (dx + dy)/2; y5 = y4 + (dx - dy)/2;
    
    scf(bitmap);
    plot2d([x3 x4 x5],[y3 y4 y5],-2)
    plot2d([ax bx],[ay by]); plot2d([bx x3],[by y3]);
    plot2d([x3 x4],[y3 y4]); plot2d([x4 ax],[y4 ay]);
    
    fcn(bitmap,x4,y4,x5,y5,depth-1);
    fcn(bitmap,x5,y5,x3,y3,depth-1);
endfunction

plot_win = scf();
final_depth = 8;
clf();

fcn(plot_win,275,500,375,500,final_depth)

scf(plot_win);
xname('Pythagoras tree: '+string(final_depth)+' levels');
set(gca(),'isoview','on');
set(gca(),'axes_visible',['off','off','off']);

Sidef

Translation of: Java
require('Imager')

func tree(img, x1, y1, x2, y2, depth) {

    depth <= 0 && return()

    var dx = (x2 - x1)
    var dy = (y1 - y2)

    var x3 = (x2 - dy)
    var y3 = (y2 - dx)
    var x4 = (x1 - dy)
    var y4 = (y1 - dx)
    var x5 = (x4 + 0.5*(dx - dy))
    var y5 = (y4 - 0.5*(dx + dy))

    # square
    img.polygon(
        points => [
            [x1, y1],
            [x2, y2],
            [x3, y3],
            [x4, y4],
        ],
        color => [0, 255/depth, 0],
    )

    # triangle
    img.polygon(
        points => [
            [x3, y3],
            [x4, y4],
            [x5, y5],
        ],
        color => [0, 255/depth, 0],
    )

    tree(img, x4, y4, x5, y5, depth - 1)
    tree(img, x5, y5, x3, y3, depth - 1)
}

var (width=1920, height=1080)
var img = %O<Imager>.new(xsize => width, ysize => height)
img.box(filled => 1, color => 'white')
tree(img, width/2.3, height, width/1.8, height, 10)
img.write(file => 'pythagoras_tree.png')

Output image: Pythagoras tree

uBasic/4tH

Translation of: BASIC256
Dim @o(5) ' 0 = SVG file, 1 = color, 2 = fillcolor, 3 = pixel, 4 = text

' === Begin Program ===

w = 800 : h = w * 11 / 16
v = w / 2 : d = w / 12

Proc _SVGopen ("pythtree.svg")           ' open the SVG file
Proc _Canvas (w, h)                      ' set the canvas size
Proc _Background (FUNC(_Color ("White")))
                                         ' we have a white background
Proc _Pythagoras_tree (v - d, h - 10, v + d, h - 10, 0)
Proc _SVGclose 
End

_Pythagoras_tree
  Param (5)
  Local (8)

  If e@ > 10 Then Return

  f@ = c@ - a@ : g@ = b@ - d@
  h@ = c@ - g@ : i@ = d@ - f@
  j@ = a@ - g@ : k@ = b@ - f@
  l@ = j@ + (f@ - g@) / 2
  m@ = k@ - (f@ + g@) / 2          

  Proc _SetColor (FUNC(_RGBtoColor (0, e@*25, 0)))
                                       ' draw the box
  Proc _Line (b@, a@, d@, c@) : Proc _Line (d@, c@, i@, h@)
  Proc _Line (i@, h@, k@, j@) : Proc _Line (k@, j@, b@, a@)

  Proc _Pythagoras_tree (j@, k@, l@, m@, e@ +1)
  Proc _Pythagoras_tree (l@, m@, h@, i@, e@ +1)
Return

' === End Program ===

_RGBtoColor Param (3) : Return (a@ * 65536 + b@ * 256 + c@)
_SetColor Param (1) : @o(1) = a@ : Return
_SVGclose Write @o(0), "</svg>" : Close @o(0) : Return
_color_ Param (1) : Proc _PrintRGB (a@) : Write @o(0), "\q />" : Return

_PrintRGB                              ' print an RBG color in hex
  Param (1)
  Radix 16

  If a@ < 0 Then
    Write @o(0), "none";
  Else
    Write @o(0), Show(Str ("#!######", a@));
  EndIf

  Radix 10
Return

_Background                            ' set the background color
  Param (1)

  Write @o(0), "<rect width=\q100%\q height=\q100%\q fill=\q";
  Proc _color_ (a@)
Return

_Color                                 ' retrieve color code from its name
  Param (1)
  Local (1)
  Radix 16

  if Comp(a@, "black") = 0 Then
    b@ = 000000
  else if Comp(a@, "blue") = 0 Then
    b@ = 0000ff
  else if Comp(a@, "green") = 0 Then
    b@ = 00ff00
  else if Comp(a@, "cyan") = 0 Then
    b@ = 00ffff
  else if Comp(a@, "red") = 0 Then
    b@ = 0ff0000
  else if Comp(a@, "magenta") = 0 Then
    b@ = 0ff00ff
  else if Comp(a@, "yellow") = 0 Then
    b@ = 0ffff00
  else if Comp(a@, "white") = 0 Then
    b@ = 0ffffff
  else if Comp(a@, "none") = 0 Then
    b@ = Info ("nil")
  else Print "Invalid color" : Raise 1
  fi : fi : fi : fi : fi : fi : fi : fi : fi

  Radix 10
Return (b@)

_Line                                  ' draw an SVG line from x1,y1 to x2,y2
  Param (4)

  Write @o(0), "<line x1=\q";d@;"\q y1=\q";c@;
  Write @o(0), "\q x2=\q";b@;"\q y2=\q";a@;"\q stroke=\q";
  Proc _color_ (@o(1))
Return

_Canvas                                ' set up a canvas x wide and y high
  Param (2)

  Write @o(0), "<svg width=\q";a@;"\q height=\q";b@;"\q viewBox=\q0 0 ";a@;" ";b@;
  Write @o(0), "\q xmlns=\qhttp://www.w3.org/2000/svg\q ";
  Write @o(0), "xmlns:xlink=\qhttp://www.w3.org/1999/xlink\q>"
Return

_SVGopen                               ' open an SVG file by name
  Param (1)

  If Set (@o(0), Open (a@, "w")) < 0 Then
     Print "Cannot open \q";Show (a@);"\q" : Raise 1
  Else
     Write @o(0), "<?xml version=\q1.0\q encoding=\qUTF-8\q standalone=\qno\q?>"
     Write @o(0), "<!DOCTYPE svg PUBLIC \q-//W3C//DTD SVG 1.1//EN\q ";
     Write @o(0), "\qhttp://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\q>"
  EndIf
Return

Wren

Translation of: Kotlin
Library: DOME
Library: Wren-polygon
import "graphics" for Canvas, Color
import "dome" for Window
import "./polygon" for Polygon

var DepthLimit = 7
var Hue = 0.15

class PythagorasTree {
    construct new(width, height) {
        Window.title = "Pythagoras Tree"
        Window.resize(width, height)
        Canvas.resize(width, height)
    }

    init() {
        Canvas.cls(Color.white)
        drawTree(275, 500, 375, 500, 0)
    }

    drawTree(x1, y1, x2, y2, depth) {
        if (depth == DepthLimit) return
        var dx = x2 - x1
        var dy = y1 - y2

        var x3 = x2 - dy
        var y3 = y2 - dx
        var x4 = x1 - dy
        var y4 = y1 - dx
        var x5 = x4 + 0.5 * (dx - dy)
        var y5 = y4 - 0.5 * (dx + dy)

        // draw a square
        var col = Color.hsv((Hue + depth * 0.02) * 360, 1, 1)
        var square = Polygon.quick([[x1, y1], [x2, y2], [x3, y3], [x4, y4]])
        square.drawfill(col)
        square.draw(Color.lightgray)

        // draw a triangle
        col = Color.hsv((Hue + depth * 0.035) * 360, 1, 1)
        var triangle = Polygon.quick([[x3, y3], [x4, y4], [x5, y5]])
        triangle.drawfill(col)
        triangle.draw(Color.lightgray)

        drawTree(x4, y4, x5, y5, depth + 1)
        drawTree(x5, y5, x3, y3, depth + 1)
    }

    update() {}

    draw(alpha) {}
}

var Game = PythagorasTree.new(640, 640)

XPL0

proc DrawTree(X1, Y1, X2, Y2, Depth);
int  X1, Y1, X2, Y2, Depth;
int  X3, Y3, X4, Y4, X5, Y5, DX, DY, Color;
[if Depth < 7 then
   [DX:= X2 - X1;  DY:= Y1 - Y2;
    X3:= X2 - DY;  Y3:= Y2 - DX;
    X4:= X1 - DY;  Y4:= Y1 - DX;
    X5:= X4 + (DX-DY)/2;  Y5:= Y4 - (DX+DY)/2;
    Color:= $2A + Depth;
    Move(X1, Y1);
    Line(X2, Y2, Color);  Line(X3, Y3, Color);
    Line(X4, Y4, Color);  Line(X1, Y1, Color);
    DrawTree(X4, Y4, X5, Y5, Depth+1);
    DrawTree(X5, Y5, X3, Y3, Depth+1);
   ];
];

def ScrW=320, ScrH=200;
[SetVid($13);
DrawTree(9*ScrW/20, 3*ScrH/4, 11*ScrW/20, 3*ScrH/4, 0);
]
Output:

Yabasic

Translation of: FreeBASIC
Sub pythagoras_tree(x1, y1, x2, y2, depth)
    local dx, dy, x3, y3, x4, y4, x5, y5
 
    If depth > limit Return
 
    dx = x2 - x1 : dy = y1 - y2
    x3 = x2 - dy : y3 = y2 - dx
    x4 = x1 - dy : y4 = y1 - dx
    x5 = x4 + (dx - dy) / 2
    y5 = y4 - (dx + dy) / 2
    //draw the box
    color 255 - depth * 20, 255, 0
    fill triangle x1, y1, x2, y2, x3, y3
    fill triangle x3, y3, x4, y4, x1, y1
    fill triangle x4, y4, x5, y5, x3, y3
 
    pythagoras_tree(x4, y4, x5, y5, depth +1)
    pythagoras_tree(x5, y5, x3, y3, depth +1)
 
End Sub
 
// ------=< MAIN >=------
w = 800 : h = int(w * 11 / 16)
w2 = int(w / 2) : diff = int(w / 12)
limit = 12
 
open window w, h
//backcolor 0, 0, 0
clear window

pythagoras_tree(w2 - diff, h -10 , w2 + diff , h -10 , 1)

zkl

I added green crosses at three of the vertexes of the new square to simulate leaves on the tree.

Translation of: Java

Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

fcn pythagorasTree{
   bitmap:=PPM(640,640,0xFF|FF|FF);  // White background

   fcn(bitmap, ax,ay, bx,by, depth=0){
      if(depth>10) return();
      dx,dy:=bx-ax, ay-by;
      x3,y3:=bx-dy, by-dx;
      x4,y4:=ax-dy, ay-dx;
      x5,y5:=x4 + (dx - dy)/2, y4 - (dx + dy)/2;
      bitmap.cross(x3,y3);bitmap.cross(x4,y4);bitmap.cross(x5,y5);
      bitmap.line(ax,ay, bx,by, 0); bitmap.line(bx,by, x3,y3, 0);
      bitmap.line(x3,y3, x4,y4, 0); bitmap.line(x4,y4, ax,ay, 0);

      self.fcn(bitmap,x4,y4, x5,y5, depth+1);
      self.fcn(bitmap,x5,y5, x3,y3, depth+1);
   }(bitmap,275,500, 375,500);

   bitmap.writeJPGFile("pythagorasTree.jpg",True);
}();