Task: Fractal tree


C++: #include <windows.h>
#include <string>
#include <math.h>


using namespace std;


const float PI = 3.1415926536f;


class myBitmap
{
public:
    myBitmap() : pen( NULL ) {}
    ~myBitmap()
    {
	DeleteObject( pen );
	DeleteDC( hdc );
	DeleteObject( bmp );
    }

    bool create( int w, int h )
    {
	BITMAPINFO	bi;
	void		*pBits;
	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 setPenColor( DWORD clr )
    {
	if( pen ) DeleteObject( pen );
	pen = CreatePen( PS_SOLID, 1, clr );
	SelectObject( hdc, pen );
    }

    void saveBitmap( string path )
    {
	BITMAPFILEHEADER	fileheader;
	BITMAPINFO			infoheader;
	BITMAP				bitmap;
	DWORD*				dwpBits;
	DWORD				wb;
	HANDLE				file;

	GetObject( bmp, sizeof( bitmap ), &bitmap );

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

	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()     { return hdc; }
    int getWidth()  { return width; }
    int getHeight() { return height; }

private:
    HBITMAP bmp;
    HDC	    hdc;
    HPEN    pen;
    int     width, height;
};

class vector2
{
public:
    vector2() { x = y = 0; }
    vector2( int a, int b ) { x = a; y = b; }
    void set( int a, int b ) { x = a; y = b; }
    void rotate( float angle_r )
    {
	float _x = static_cast<float>( x ),
	      _y = static_cast<float>( y ),
	       s = sinf( angle_r ), 
	       c = cosf( angle_r ),
	       a = _x * c - _y * s, 
	       b = _x * s + _y * c;

	x = static_cast<int>( a ); 
	y = static_cast<int>( b );
    }

    int x, y;
};

class fractalTree
{
public:
    fractalTree()		      { _ang = DegToRadian( 24.0f ); }
    float DegToRadian( float degree ) { return degree * ( PI / 180.0f ); }

    void create( myBitmap* bmp )
    {
	_bmp = bmp;
	float line_len = 130.0f;

	vector2 sp( _bmp->getWidth() / 2, _bmp->getHeight() - 1 );
	MoveToEx( _bmp->getDC(), sp.x, sp.y, NULL );
	sp.y -= static_cast<int>( line_len );
	LineTo( _bmp->getDC(), sp.x, sp.y);

	drawRL( &sp, line_len, 0, true );
	drawRL( &sp, line_len, 0, false );
    }

private:
    void drawRL( vector2* sp, float line_len, float a, bool rg )
    {
	line_len *= .75f;
	if( line_len < 2.0f ) return;

	MoveToEx( _bmp->getDC(), sp->x, sp->y, NULL );
	vector2 r( 0, static_cast<int>( line_len ) );

        if( rg ) a -= _ang;
        else a += _ang; 

	r.rotate( a );
	r.x += sp->x; r.y = sp->y - r.y;

	LineTo( _bmp->getDC(), r.x, r.y );

	drawRL( &r, line_len, a, true );
	drawRL( &r, line_len, a, false );
    }

    myBitmap* _bmp;
    float     _ang;
};

int main( int argc, char* argv[] )
{
    ShowWindow( GetConsoleWindow(), SW_MAXIMIZE );

    myBitmap bmp;
    bmp.create( 640, 512 );
    bmp.setPenColor( RGB( 255, 255, 0 ) );

    fractalTree tree;
    tree.create( &bmp );
	
    BitBlt( GetDC( GetConsoleWindow() ), 0, 20, 648, 512, bmp.getDC(), 0, 0, SRCCOPY );

    bmp.saveBitmap( "f:
	
    system( "pause" );
	
    return 0;
}











Ada: with Ada.Numerics.Elementary_Functions;

with SDL.Video.Windows.Makers;
with SDL.Video.Renderers.Makers;
with SDL.Video.Rectangles;
with SDL.Events.Events;

procedure Fractal_Tree is

   Width   : constant := 600;
   Height  : constant := 600;
   Level   : constant := 13;
   Length  : constant := 130.0;
   X_Start : constant := 475.0;
   Y_Start : constant := 580.0;
   A_Start : constant := -1.54;
   Angle_1 : constant := 0.10;
   Angle_2 : constant := 0.35;
   C_1     : constant := 0.71;
   C_2     : constant := 0.87;

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

   procedure Draw_Tree (Level  : in Natural;
                        Length : in Float;
                        Angle  : in Float;
                        X, Y   : in Float)
   is
      use SDL;
      use Ada.Numerics.Elementary_Functions;
      Pi   : constant       := Ada.Numerics.Pi;
      X_2  : constant Float := X + Length * Cos (Angle, 2.0 * Pi);
      Y_2  : constant Float := Y + Length * Sin (Angle, 2.0 * Pi);
      Line : constant SDL.Video.Rectangles.Line_Segment
        := ((C.int (X), C.int (Y)), (C.int (X_2), C.int (Y_2)));
   begin
      if Level > 0 then
         Renderer.Set_Draw_Colour (Colour => (0, 220, 0, 255));
         Renderer.Draw (Line => Line);

         Draw_Tree (Level - 1, C_1 * Length, Angle + Angle_1, X_2, Y_2);
         Draw_Tree (Level - 1, C_2 * Length, Angle - Angle_2, X_2, Y_2);
      end if;
   end Draw_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    => "Fractal 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));

   Draw_Tree (Level, Length, A_Start, X_Start, Y_Start);
   Window.Update_Surface;

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