]> git.saurik.com Git - wxWidgets.git/blob - demos/fractal/fractal.cpp
5f73ce6ace2bba7397e8f09078ae91c08674ce69
[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 #include "wx/stockitem.h"
47
48 #include <stdlib.h>
49 #include <time.h>
50
51 #define Random(x) (rand() % x)
52 #define Randomize() (srand((unsigned int)time(NULL)))
53
54 static int detail = 9; // CHANGE THIS... 7,8,9 etc
55
56 static bool running = false;
57 static wxMenuBar *menuBar = NULL;
58
59 // Define a new application type
60 class MyApp: public wxApp
61 {
62 public:
63 bool OnInit();
64 };
65
66 IMPLEMENT_APP(MyApp)
67
68 // Define a new frame type
69 class MyFrame: public wxFrame
70 {
71 public:
72 MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size);
73
74 void OnCloseWindow(wxCloseEvent& event);
75 void OnExit(wxCommandEvent& event);
76
77 DECLARE_EVENT_TABLE()
78 };
79
80 // Define a new canvas which can receive some events
81 class MyCanvas: public wxWindow
82 {
83 public:
84 MyCanvas(wxFrame *frame);
85 void Draw(wxDC& dc);
86
87 private:
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;
93
94 DECLARE_EVENT_TABLE()
95 };
96
97 // `Main program' equivalent, creating windows and returning main app frame
98 bool MyApp::OnInit()
99 {
100 // Create the main frame window
101 MyFrame *frame = new MyFrame(NULL, _T("Fractal Mountains for wxWidgets"), wxDefaultPosition, wxSize(640, 480));
102
103 // Make a menubar
104 wxMenu *file_menu = new wxMenu;
105 file_menu->Append(wxID_EXIT, wxGetStockLabel(wxID_EXIT));
106 menuBar = new wxMenuBar;
107 menuBar->Append(file_menu, _T("&File"));
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
116 frame->Show(true);
117
118 return true;
119 }
120
121 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
122 EVT_CLOSE(MyFrame::OnCloseWindow)
123 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
124 END_EVENT_TABLE()
125
126 // My frame constructor
127 MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size):
128 wxFrame(frame, wxID_ANY, title, pos, size, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE )
129 {
130 }
131
132 // Intercept menu commands
133 void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
134 {
135 this->Destroy();
136 }
137
138 void MyFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
139 {
140 static bool destroyed = false;
141 if (destroyed)
142 return;
143
144 this->Destroy();
145
146 destroyed = true;
147 }
148
149 BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
150 EVT_PAINT(MyCanvas::OnPaint)
151 END_EVENT_TABLE()
152
153 // Define a constructor for my canvas
154 MyCanvas::MyCanvas(wxFrame *frame):
155 wxWindow(frame, wxID_ANY)
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
170 void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
171 {
172 wxPaintDC dc(this);
173 PrepareDC(dc);
174 Draw(dc);
175 }
176
177 void MyCanvas::Draw(wxDC& dc)
178 {
179 if (running) return;
180
181 running = true;
182 menuBar->EnableTop(0, false);
183
184 Randomize();
185
186 dc.SetBackground(*wxLIGHT_GREY_BRUSH);
187 dc.Clear();
188
189 int Left, Top, Right, Bottom;
190 GetClientSize(&Right, &Bottom);
191
192 Right *= 3; Right /= 4;
193 Bottom *= 3; Bottom /= 4;
194 Left = 0;
195 Top = Bottom/8;
196
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;
202
203 dc.SetBrush(WaterBrush);
204 dc.DrawPolygon(4, Water);
205
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;
211
212 Fractal(dc, Left, Top, Right, Bottom, 0, 0, 0, 0, detail, Std, Ratio);
213
214 menuBar->EnableTop(0, true);
215 running = false;
216 }
217
218 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)
219 {
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 }
262 }
263