wx/math.h integration
[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 wxWidgets, 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 "wx/math.h"
46
47 #include <stdlib.h>
48 #include <time.h>
49
50 #define Random(x) (rand() % x)
51 #define Randomize() (srand((unsigned int)time(NULL)))
52
53 static int detail = 9; // CHANGE THIS... 7,8,9 etc
54
55 static bool running = false;
56 static wxMenuBar *menuBar = NULL;
57
58 // Define a new application type
59 class MyApp: public wxApp
60 {
61 public:
62 bool OnInit();
63 };
64
65 IMPLEMENT_APP(MyApp)
66
67 // Define a new frame type
68 class MyFrame: public wxFrame
69 {
70 public:
71 MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size);
72
73 void OnCloseWindow(wxCloseEvent& event);
74 void OnExit(wxCommandEvent& event);
75
76 DECLARE_EVENT_TABLE()
77 };
78
79 // Define a new canvas which can receive some events
80 class MyCanvas: public wxWindow
81 {
82 public:
83 MyCanvas(wxFrame *frame);
84 void Draw(wxDC& dc);
85
86 private:
87 void OnPaint(wxPaintEvent& event);
88 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);
89 wxPen SnowPen, MtnPen, GreenPen;
90 wxBrush WaterBrush;
91 int Sealevel;
92
93 DECLARE_EVENT_TABLE()
94 };
95
96 // `Main program' equivalent, creating windows and returning main app frame
97 bool MyApp::OnInit()
98 {
99 // Create the main frame window
100 MyFrame *frame = new MyFrame(NULL, _T("Fractal Mountains for wxWidgets"), wxDefaultPosition, wxSize(640, 480));
101
102 // Make a menubar
103 wxMenu *file_menu = new wxMenu;
104 file_menu->Append(wxID_EXIT, _T("E&xit"));
105 menuBar = new wxMenuBar;
106 menuBar->Append(file_menu, _T("&File"));
107 frame->SetMenuBar(menuBar);
108
109 int width, height;
110 frame->GetClientSize(&width, &height);
111
112 (void) new MyCanvas(frame);
113
114 // Show the frame
115 frame->Show(true);
116
117 return true;
118 }
119
120 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
121 EVT_CLOSE(MyFrame::OnCloseWindow)
122 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
123 END_EVENT_TABLE()
124
125 // My frame constructor
126 MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size):
127 wxFrame(frame, wxID_ANY, title, pos, size, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE )
128 {
129 }
130
131 // Intercept menu commands
132 void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
133 {
134 this->Destroy();
135 }
136
137 void MyFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
138 {
139 static bool destroyed = false;
140 if (destroyed)
141 return;
142
143 this->Destroy();
144
145 destroyed = true;
146 }
147
148 BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
149 EVT_PAINT(MyCanvas::OnPaint)
150 END_EVENT_TABLE()
151
152 // Define a constructor for my canvas
153 MyCanvas::MyCanvas(wxFrame *frame):
154 wxWindow(frame, wxID_ANY)
155 {
156 wxColour wxCol1(255,255,255);
157 SnowPen = wxPen(wxCol1, 2, wxSOLID);
158
159 wxColour wxCol2(128,0,0);
160 MtnPen = wxPen(wxCol2, 1, wxSOLID);
161
162 wxColour wxCol3(0,128,0);
163 GreenPen = wxPen(wxCol3, 1, wxSOLID);
164
165 wxColour wxCol4(0,0,128);
166 WaterBrush = wxBrush(wxCol4, wxSOLID);
167 }
168
169 void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
170 {
171 wxPaintDC dc(this);
172 PrepareDC(dc);
173 Draw(dc);
174 }
175
176 void MyCanvas::Draw(wxDC& dc)
177 {
178 if (running) return;
179
180 running = true;
181 menuBar->EnableTop(0, false);
182
183 Randomize();
184
185 dc.SetBackground(*wxLIGHT_GREY_BRUSH);
186 dc.Clear();
187
188 int Left, Top, Right, Bottom;
189 GetClientSize(&Right, &Bottom);
190
191 Right *= 3; Right /= 4;
192 Bottom *= 3; Bottom /= 4;
193 Left = 0;
194 Top = Bottom/8;
195
196 wxPoint Water[4];
197 Water[0].x = Left; Water[0].y = Top;
198 Water[1].x = Right; Water[1].y = Top;
199 Water[2].x = Right+Bottom/2; Water[2].y = Bottom;
200 Water[3].x = Bottom/2; Water[3].y = Bottom;
201
202 dc.SetBrush(WaterBrush);
203 dc.DrawPolygon(4, Water);
204
205 double H = 0.75;
206 double Scale = Bottom;
207 double Ratio = 1.0 / pow(2.0, H);
208 double Std = Scale * Ratio;
209 Sealevel = Random(18) - 8;
210
211 Fractal(dc, Left, Top, Right, Bottom, 0, 0, 0, 0, detail, Std, Ratio);
212
213 menuBar->EnableTop(0, true);
214 running = false;
215 }
216
217 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)
218 {
219 int Xmid = (X1 + X2) / 2;
220 int Ymid = (Y1 + Y2) / 2;
221 int Z23 = (Z2 + Z3) / 2;
222 int Z41 = (Z4 + Z1) / 2;
223 int Newz = (int)((Z1 + Z2 + Z3 + Z4) / 4 + (double)(Random(17) - 8) / 8.0 * Std);
224
225 if (--Iteration)
226 {
227 int Z12 = (Z1 + Z2) / 2;
228 int Z34 = (Z3 + Z4) / 2;
229 double Stdmid = Std * Ratio;
230
231 Fractal(dc, Xmid, Y1, X2, Ymid, Z12, Z2, Z23, Newz, Iteration, Stdmid, Ratio);
232 Fractal(dc, X1, Y1, Xmid, Ymid, Z1, Z12, Newz, Z41, Iteration, Stdmid, Ratio);
233 Fractal(dc, Xmid, Ymid, X2, Y2, Newz, Z23, Z3, Z34, Iteration, Stdmid, Ratio);
234 Fractal(dc, X1, Ymid, Xmid, Y2, Z41, Newz, Z34, Z4, Iteration, Stdmid, Ratio);
235 }
236 else
237 {
238 if (Newz <= Sealevel)
239 {
240 wxPoint P[4];
241 P[0].x = Y1 / 2 + X1; P[0].y = Y1 + Z1;
242 P[1].x = Y1 / 2 + X2; P[1].y = Y1 + Z2;
243 P[2].x = Y2 / 2 + X2; P[2].y = Y2 + Z3;
244 P[3].x = Y2 / 2 + X1; P[3].y = Y2 + Z4;
245
246 dc.SetPen(* wxBLACK_PEN);
247 dc.SetBrush(* wxBLACK_BRUSH);
248
249 dc.DrawPolygon(4, P);
250
251 if (Z1 >= -(60+Random(25)))
252 dc.SetPen(GreenPen);
253 else if (Z1 >= -(100+Random(25)))
254 dc.SetPen(MtnPen);
255 else
256 dc.SetPen(SnowPen);
257
258 dc.DrawLine(Ymid/2+X2, Ymid+Z23, Ymid/2+X1, Ymid+Z41);
259 }
260 }
261 }
262