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 trig functions).

Related tasks



C++[edit]

Pythagoras treeCpp.png

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;
}
 

F#[edit]

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[edit]

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

Haskell[edit]

Haskell allows to make highly modular solution.

This function builds a pair of minor squares based on a given square (a square is represented as a list of points). Here all vector arithmetics is hidden.

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)

Now we are ready to build a set of squares, forming the 10-generation tree. The function mkBranches returns a list of results, in order to apply this function iteratively we define a monadic iteration iterateM.

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 result of squares function is a raw data which could be displayed as a tree in OpenGL window using Gloss library:

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

or in raw 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]

or in PNG (SVG, JPG,...) via gnuplot

import Graphics.EasyPlot
 
main = plot (PNG "pith.png") $ map (mkLine . close) squares
where mkLine = Data2D [Style Lines, Color Black,Title ""] []
close lst = lst ++ [head lst]

Java[edit]

Pythagoras tree java.png
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);
});
}
}

Kotlin[edit]

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)
}
}
}

PARI/GP[edit]

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, 0,size);
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[edit]

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');

Perl 6[edit]

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);

Phix[edit]

Translation of: Java

Included in the distro as demo\rosetta\PythagorasTree.exw

include ..\pGUI\pGUI.e
 
Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas
 
function rgb(integer r, integer g, integer b)
return r*#10000 + g*#100 + b
end function
 
procedure drawTree(atom x1, atom y1, atom x2, atom y2, integer depth)
atom dx = x2 - x1
atom dy = y1 - y2
 
atom x3 = x2 - dy
atom y3 = y2 - dx
atom x4 = x1 - dy
atom y4 = y1 - dx
atom x5 = x4 + 0.5 * (dx - dy)
atom y5 = y4 - 0.5 * (dx + dy)
 
integer r = 250-depth*20
 
cdCanvasSetForeground(cddbuffer, rgb(r,#FF,0))
cdCanvasBegin(cddbuffer,CD_FILL)
cdCanvasVertex(cddbuffer, x1, 640-y1)
cdCanvasVertex(cddbuffer, x2, 640-y2)
cdCanvasVertex(cddbuffer, x3, 640-y3)
cdCanvasVertex(cddbuffer, x4, 640-y4)
cdCanvasEnd(cddbuffer)
 
cdCanvasSetForeground(cddbuffer, CD_GRAY)
cdCanvasBegin(cddbuffer,CD_CLOSED_LINES)
cdCanvasVertex(cddbuffer, x1, 640-y1)
cdCanvasVertex(cddbuffer, x2, 640-y2)
cdCanvasVertex(cddbuffer, x3, 640-y3)
cdCanvasVertex(cddbuffer, x4, 640-y4)
cdCanvasEnd(cddbuffer)
 
cdCanvasSetForeground(cddbuffer, rgb(r-depth*10,#FF,0))
cdCanvasBegin(cddbuffer,CD_FILL)
cdCanvasVertex(cddbuffer, x3, 640-y3)
cdCanvasVertex(cddbuffer, x4, 640-y4)
cdCanvasVertex(cddbuffer, x5, 640-y5)
cdCanvasEnd(cddbuffer)
 
cdCanvasSetForeground(cddbuffer, CD_GRAY)
cdCanvasBegin(cddbuffer,CD_CLOSED_LINES)
cdCanvasVertex(cddbuffer, x3, 640-y3)
cdCanvasVertex(cddbuffer, x4, 640-y4)
cdCanvasVertex(cddbuffer, x5, 640-y5)
cdCanvasEnd(cddbuffer)
 
if depth<8 then
drawTree(x4, y4, x5, y5, depth + 1)
drawTree(x5, y5, x3, y3, depth + 1)
end if
end procedure
 
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)
cdCanvasActivate(cddbuffer)
drawTree(275, 500, 375, 500, 0)
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
 
function esc_close(Ihandle /*ih*/, atom c)
if c=K_ESC then return IUP_CLOSE end if
return IUP_CONTINUE
end function
 
procedure main()
IupOpen("..\\pGUI\\")
 
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")
IupSetCallback(dlg, "K_ANY", Icallback("esc_close"))
 
IupShow(dlg)
IupMainLoop()
IupClose()
end procedure
 
main()

Processing[edit]

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);
}

PurePasic[edit]

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

R[edit]

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 

Racket[edit]

#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)

Sidef[edit]

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 = %s<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')

zkl[edit]

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

PythagorasTreeWithLeafs.zkl.jpg
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);
}();