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