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