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