]> git.saurik.com Git - wxWidgets.git/blame - demos/fractal/fractal.cpp
correct access for virtuals
[wxWidgets.git] / demos / fractal / fractal.cpp
CommitLineData
025e88c5
JS
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/*
14Date: Tue, 5 Apr 1994 12:01:18 +1000
15From: Andrew Davison <andrewd@au.com.sfe>
16To: wxwin-users@ed.aiai
17Subject: Fractal mountains
18
19Hi,
20
21This is a quick port of a fractal mountain generator originally
22done for MS-Windows. On a Sun the colours look a little washed
23out and there is not as much snow or high mountains (maybe the
24random number generators fault). The viewing plane is not
25quite right as the original code used SetViewportOrg() which there
be5a51fb 26doesn't seem to be an equivalent of under wxWidgets, and my quick
b713f891 27hack doesn't fix.
025e88c5
JS
28*/
29
025e88c5
JS
30#include "wx/wxprec.h"
31
c4b77901
JS
32#ifdef __BORLANDC__
33 #pragma hdrstop
34#endif
35
025e88c5
JS
36#ifndef WX_PRECOMP
37 #include "wx/wx.h"
38#endif //precompiled headers
39
b713f891 40#include "wx/math.h"
5d2ac6b8 41#include "wx/stockitem.h"
b713f891 42
025e88c5 43#include <stdlib.h>
025e88c5
JS
44#include <time.h>
45
46#define Random(x) (rand() % x)
47#define Randomize() (srand((unsigned int)time(NULL)))
48
e0e31ccd 49static int detail = 9; // CHANGE THIS... 7,8,9 etc
025e88c5 50
b713f891 51static bool running = false;
025e88c5
JS
52static wxMenuBar *menuBar = NULL;
53
54// Define a new application type
55class MyApp: public wxApp
e0e31ccd
WS
56{
57public:
58 bool OnInit();
025e88c5
JS
59};
60
61IMPLEMENT_APP(MyApp)
62
63// Define a new frame type
64class MyFrame: public wxFrame
65{
66public:
e0e31ccd 67 MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size);
025e88c5 68
e0e31ccd 69 void OnCloseWindow(wxCloseEvent& event);
025e88c5 70 void OnExit(wxCommandEvent& event);
e0e31ccd
WS
71
72 DECLARE_EVENT_TABLE()
025e88c5
JS
73};
74
75// Define a new canvas which can receive some events
76class MyCanvas: public wxWindow
77{
78public:
e0e31ccd
WS
79 MyCanvas(wxFrame *frame);
80 void Draw(wxDC& dc);
025e88c5
JS
81
82private:
e0e31ccd
WS
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;
025e88c5
JS
88
89DECLARE_EVENT_TABLE()
90};
91
92// `Main program' equivalent, creating windows and returning main app frame
93bool MyApp::OnInit()
94{
95 // Create the main frame window
e0e31ccd 96 MyFrame *frame = new MyFrame(NULL, _T("Fractal Mountains for wxWidgets"), wxDefaultPosition, wxSize(640, 480));
025e88c5
JS
97
98 // Make a menubar
99 wxMenu *file_menu = new wxMenu;
5d2ac6b8 100 file_menu->Append(wxID_EXIT, wxGetStockLabel(wxID_EXIT));
025e88c5 101 menuBar = new wxMenuBar;
f37c24e0 102 menuBar->Append(file_menu, _T("&File"));
025e88c5
JS
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
e0e31ccd 111 frame->Show(true);
025e88c5 112
e0e31ccd 113 return true;
025e88c5
JS
114}
115
116BEGIN_EVENT_TABLE(MyFrame, wxFrame)
117 EVT_CLOSE(MyFrame::OnCloseWindow)
118 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
119END_EVENT_TABLE()
120
121// My frame constructor
122MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size):
e0e31ccd 123 wxFrame(frame, wxID_ANY, title, pos, size, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE )
025e88c5
JS
124{
125}
126
127// Intercept menu commands
babd36de 128void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
025e88c5
JS
129{
130 this->Destroy();
131}
132
babd36de 133void MyFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
025e88c5 134{
e0e31ccd 135 static bool destroyed = false;
025e88c5
JS
136 if (destroyed)
137 return;
138
139 this->Destroy();
140
e0e31ccd 141 destroyed = true;
025e88c5
JS
142}
143
144BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
145 EVT_PAINT(MyCanvas::OnPaint)
146END_EVENT_TABLE()
147
148// Define a constructor for my canvas
149MyCanvas::MyCanvas(wxFrame *frame):
e0e31ccd 150 wxWindow(frame, wxID_ANY)
025e88c5
JS
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
babd36de 165void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
025e88c5
JS
166{
167 wxPaintDC dc(this);
e0e31ccd
WS
168 PrepareDC(dc);
169 Draw(dc);
025e88c5
JS
170}
171
172void MyCanvas::Draw(wxDC& dc)
173{
174 if (running) return;
b713f891 175
e0e31ccd
WS
176 running = true;
177 menuBar->EnableTop(0, false);
178
179 Randomize();
025e88c5 180
e0e31ccd
WS
181 dc.SetBackground(*wxLIGHT_GREY_BRUSH);
182 dc.Clear();
025e88c5 183
e0e31ccd
WS
184 int Left, Top, Right, Bottom;
185 GetClientSize(&Right, &Bottom);
025e88c5 186
e0e31ccd
WS
187 Right *= 3; Right /= 4;
188 Bottom *= 3; Bottom /= 4;
189 Left = 0;
190 Top = Bottom/8;
025e88c5 191
e0e31ccd
WS
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;
025e88c5 197
e0e31ccd
WS
198 dc.SetBrush(WaterBrush);
199 dc.DrawPolygon(4, Water);
025e88c5 200
e0e31ccd
WS
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;
025e88c5 206
e0e31ccd 207 Fractal(dc, Left, Top, Right, Bottom, 0, 0, 0, 0, detail, Std, Ratio);
025e88c5 208
e0e31ccd
WS
209 menuBar->EnableTop(0, true);
210 running = false;
025e88c5
JS
211}
212
213void 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{
e0e31ccd
WS
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 }
025e88c5
JS
257}
258