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