]> git.saurik.com Git - wxWidgets.git/blame - demos/fractal/fractal.cpp
update from James Bishop
[wxWidgets.git] / demos / fractal / fractal.cpp
CommitLineData
025e88c5
JS
1///////////////////////////////////////////////////////////////////////////////
2// Name: fractal.cpp
3// Purpose: demo of wxConfig and related classes
4// Author: Andrew Davison
5// Modified by:
6// Created: 05.04.94
7// RCS-ID: $Id$
8// Copyright: (c) 1994 Andrew Davison
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12
13/*
14Date: Tue, 5 Apr 1994 12:01:18 +1000
15From: Andrew Davison <andrewd@au.com.sfe>
16To: wxwin-users@ed.aiai
17Subject: Fractal mountains
18
19Hi,
20
21This is a quick port of a fractal mountain generator originally
22done for MS-Windows. On a Sun the colours look a little washed
23out and there is not as much snow or high mountains (maybe the
24random number generators fault). The viewing plane is not
25quite right as the original code used SetViewportOrg() which there
be5a51fb 26doesn't seem to be an equivalent of under wxWidgets, and my quick
b713f891 27hack doesn't fix.
025e88c5
JS
28*/
29
30#ifdef __GNUG__
31#pragma implementation
32#pragma interface
33#endif
34
35#include "wx/wxprec.h"
36
c4b77901
JS
37#ifdef __BORLANDC__
38 #pragma hdrstop
39#endif
40
025e88c5
JS
41#ifndef WX_PRECOMP
42 #include "wx/wx.h"
43#endif //precompiled headers
44
b713f891 45#include "wx/math.h"
5d2ac6b8 46#include "wx/stockitem.h"
b713f891 47
025e88c5 48#include <stdlib.h>
025e88c5
JS
49#include <time.h>
50
51#define Random(x) (rand() % x)
52#define Randomize() (srand((unsigned int)time(NULL)))
53
e0e31ccd 54static int detail = 9; // CHANGE THIS... 7,8,9 etc
025e88c5 55
b713f891 56static bool running = false;
025e88c5
JS
57static wxMenuBar *menuBar = NULL;
58
59// Define a new application type
60class MyApp: public wxApp
e0e31ccd
WS
61{
62public:
63 bool OnInit();
025e88c5
JS
64};
65
66IMPLEMENT_APP(MyApp)
67
68// Define a new frame type
69class MyFrame: public wxFrame
70{
71public:
e0e31ccd 72 MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size);
025e88c5 73
e0e31ccd 74 void OnCloseWindow(wxCloseEvent& event);
025e88c5 75 void OnExit(wxCommandEvent& event);
e0e31ccd
WS
76
77 DECLARE_EVENT_TABLE()
025e88c5
JS
78};
79
80// Define a new canvas which can receive some events
81class MyCanvas: public wxWindow
82{
83public:
e0e31ccd
WS
84 MyCanvas(wxFrame *frame);
85 void Draw(wxDC& dc);
025e88c5
JS
86
87private:
e0e31ccd
WS
88 void OnPaint(wxPaintEvent& event);
89 void Fractal(wxDC& dc, int X1, int Y1, int X2, int Y2, int Z1, int Z2, int Z3, int Z4, int Iteration, double Std, double Ratio);
90 wxPen SnowPen, MtnPen, GreenPen;
91 wxBrush WaterBrush;
92 int Sealevel;
025e88c5
JS
93
94DECLARE_EVENT_TABLE()
95};
96
97// `Main program' equivalent, creating windows and returning main app frame
98bool MyApp::OnInit()
99{
100 // Create the main frame window
e0e31ccd 101 MyFrame *frame = new MyFrame(NULL, _T("Fractal Mountains for wxWidgets"), wxDefaultPosition, wxSize(640, 480));
025e88c5
JS
102
103 // Make a menubar
104 wxMenu *file_menu = new wxMenu;
5d2ac6b8 105 file_menu->Append(wxID_EXIT, wxGetStockLabel(wxID_EXIT));
025e88c5 106 menuBar = new wxMenuBar;
f37c24e0 107 menuBar->Append(file_menu, _T("&File"));
025e88c5
JS
108 frame->SetMenuBar(menuBar);
109
110 int width, height;
111 frame->GetClientSize(&width, &height);
112
113 (void) new MyCanvas(frame);
114
115 // Show the frame
e0e31ccd 116 frame->Show(true);
025e88c5 117
e0e31ccd 118 return true;
025e88c5
JS
119}
120
121BEGIN_EVENT_TABLE(MyFrame, wxFrame)
122 EVT_CLOSE(MyFrame::OnCloseWindow)
123 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
124END_EVENT_TABLE()
125
126// My frame constructor
127MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size):
e0e31ccd 128 wxFrame(frame, wxID_ANY, title, pos, size, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE )
025e88c5
JS
129{
130}
131
132// Intercept menu commands
babd36de 133void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
025e88c5
JS
134{
135 this->Destroy();
136}
137
babd36de 138void MyFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
025e88c5 139{
e0e31ccd 140 static bool destroyed = false;
025e88c5
JS
141 if (destroyed)
142 return;
143
144 this->Destroy();
145
e0e31ccd 146 destroyed = true;
025e88c5
JS
147}
148
149BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
150 EVT_PAINT(MyCanvas::OnPaint)
151END_EVENT_TABLE()
152
153// Define a constructor for my canvas
154MyCanvas::MyCanvas(wxFrame *frame):
e0e31ccd 155 wxWindow(frame, wxID_ANY)
025e88c5
JS
156{
157 wxColour wxCol1(255,255,255);
158 SnowPen = wxPen(wxCol1, 2, wxSOLID);
159
160 wxColour wxCol2(128,0,0);
161 MtnPen = wxPen(wxCol2, 1, wxSOLID);
162
163 wxColour wxCol3(0,128,0);
164 GreenPen = wxPen(wxCol3, 1, wxSOLID);
165
166 wxColour wxCol4(0,0,128);
167 WaterBrush = wxBrush(wxCol4, wxSOLID);
168}
169
babd36de 170void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
025e88c5
JS
171{
172 wxPaintDC dc(this);
e0e31ccd
WS
173 PrepareDC(dc);
174 Draw(dc);
025e88c5
JS
175}
176
177void MyCanvas::Draw(wxDC& dc)
178{
179 if (running) return;
b713f891 180
e0e31ccd
WS
181 running = true;
182 menuBar->EnableTop(0, false);
183
184 Randomize();
025e88c5 185
e0e31ccd
WS
186 dc.SetBackground(*wxLIGHT_GREY_BRUSH);
187 dc.Clear();
025e88c5 188
e0e31ccd
WS
189 int Left, Top, Right, Bottom;
190 GetClientSize(&Right, &Bottom);
025e88c5 191
e0e31ccd
WS
192 Right *= 3; Right /= 4;
193 Bottom *= 3; Bottom /= 4;
194 Left = 0;
195 Top = Bottom/8;
025e88c5 196
e0e31ccd
WS
197 wxPoint Water[4];
198 Water[0].x = Left; Water[0].y = Top;
199 Water[1].x = Right; Water[1].y = Top;
200 Water[2].x = Right+Bottom/2; Water[2].y = Bottom;
201 Water[3].x = Bottom/2; Water[3].y = Bottom;
025e88c5 202
e0e31ccd
WS
203 dc.SetBrush(WaterBrush);
204 dc.DrawPolygon(4, Water);
025e88c5 205
e0e31ccd
WS
206 double H = 0.75;
207 double Scale = Bottom;
208 double Ratio = 1.0 / pow(2.0, H);
209 double Std = Scale * Ratio;
210 Sealevel = Random(18) - 8;
025e88c5 211
e0e31ccd 212 Fractal(dc, Left, Top, Right, Bottom, 0, 0, 0, 0, detail, Std, Ratio);
025e88c5 213
e0e31ccd
WS
214 menuBar->EnableTop(0, true);
215 running = false;
025e88c5
JS
216}
217
218void MyCanvas::Fractal(wxDC& dc, int X1, int Y1, int X2, int Y2, int Z1, int Z2, int Z3, int Z4, int Iteration, double Std, double Ratio)
219{
e0e31ccd
WS
220 int Xmid = (X1 + X2) / 2;
221 int Ymid = (Y1 + Y2) / 2;
222 int Z23 = (Z2 + Z3) / 2;
223 int Z41 = (Z4 + Z1) / 2;
224 int Newz = (int)((Z1 + Z2 + Z3 + Z4) / 4 + (double)(Random(17) - 8) / 8.0 * Std);
225
226 if (--Iteration)
227 {
228 int Z12 = (Z1 + Z2) / 2;
229 int Z34 = (Z3 + Z4) / 2;
230 double Stdmid = Std * Ratio;
231
232 Fractal(dc, Xmid, Y1, X2, Ymid, Z12, Z2, Z23, Newz, Iteration, Stdmid, Ratio);
233 Fractal(dc, X1, Y1, Xmid, Ymid, Z1, Z12, Newz, Z41, Iteration, Stdmid, Ratio);
234 Fractal(dc, Xmid, Ymid, X2, Y2, Newz, Z23, Z3, Z34, Iteration, Stdmid, Ratio);
235 Fractal(dc, X1, Ymid, Xmid, Y2, Z41, Newz, Z34, Z4, Iteration, Stdmid, Ratio);
236 }
237 else
238 {
239 if (Newz <= Sealevel)
240 {
241 wxPoint P[4];
242 P[0].x = Y1 / 2 + X1; P[0].y = Y1 + Z1;
243 P[1].x = Y1 / 2 + X2; P[1].y = Y1 + Z2;
244 P[2].x = Y2 / 2 + X2; P[2].y = Y2 + Z3;
245 P[3].x = Y2 / 2 + X1; P[3].y = Y2 + Z4;
246
247 dc.SetPen(* wxBLACK_PEN);
248 dc.SetBrush(* wxBLACK_BRUSH);
249
250 dc.DrawPolygon(4, P);
251
252 if (Z1 >= -(60+Random(25)))
253 dc.SetPen(GreenPen);
254 else if (Z1 >= -(100+Random(25)))
255 dc.SetPen(MtnPen);
256 else
257 dc.SetPen(SnowPen);
258
259 dc.DrawLine(Ymid/2+X2, Ymid+Z23, Ymid/2+X1, Ymid+Z41);
260 }
261 }
025e88c5
JS
262}
263