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