]> git.saurik.com Git - wxWidgets.git/blame - demos/fractal/fractal.cpp
Use wxFindWindowAtPoint() for hit testing in wxPopupTransientWindow.
[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
025e88c5
JS
7// Copyright: (c) 1994 Andrew Davison
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11
12/*
13Date: Tue, 5 Apr 1994 12:01:18 +1000
14From: Andrew Davison <andrewd@au.com.sfe>
15To: wxwin-users@ed.aiai
16Subject: Fractal mountains
17
18Hi,
19
20This is a quick port of a fractal mountain generator originally
21done for MS-Windows. On a Sun the colours look a little washed
22out and there is not as much snow or high mountains (maybe the
23random number generators fault). The viewing plane is not
24quite right as the original code used SetViewportOrg() which there
be5a51fb 25doesn't seem to be an equivalent of under wxWidgets, and my quick
b713f891 26hack doesn't fix.
025e88c5
JS
27*/
28
025e88c5
JS
29#include "wx/wxprec.h"
30
c4b77901
JS
31#ifdef __BORLANDC__
32 #pragma hdrstop
33#endif
34
025e88c5
JS
35#ifndef WX_PRECOMP
36 #include "wx/wx.h"
37#endif //precompiled headers
38
b713f891 39#include "wx/math.h"
5d2ac6b8 40#include "wx/stockitem.h"
b713f891 41
025e88c5 42#include <stdlib.h>
025e88c5
JS
43#include <time.h>
44
45#define Random(x) (rand() % x)
46#define Randomize() (srand((unsigned int)time(NULL)))
47
e0e31ccd 48static int detail = 9; // CHANGE THIS... 7,8,9 etc
025e88c5 49
b713f891 50static bool running = false;
025e88c5
JS
51static wxMenuBar *menuBar = NULL;
52
53// Define a new application type
54class MyApp: public wxApp
e0e31ccd
WS
55{
56public:
57 bool OnInit();
025e88c5
JS
58};
59
60IMPLEMENT_APP(MyApp)
61
62// Define a new frame type
63class MyFrame: public wxFrame
64{
65public:
e0e31ccd 66 MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size);
025e88c5 67
e0e31ccd 68 void OnCloseWindow(wxCloseEvent& event);
025e88c5 69 void OnExit(wxCommandEvent& event);
e0e31ccd
WS
70
71 DECLARE_EVENT_TABLE()
025e88c5
JS
72};
73
74// Define a new canvas which can receive some events
75class MyCanvas: public wxWindow
76{
77public:
e0e31ccd
WS
78 MyCanvas(wxFrame *frame);
79 void Draw(wxDC& dc);
025e88c5
JS
80
81private:
e0e31ccd
WS
82 void OnPaint(wxPaintEvent& event);
83 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);
84 wxPen SnowPen, MtnPen, GreenPen;
85 wxBrush WaterBrush;
86 int Sealevel;
025e88c5
JS
87
88DECLARE_EVENT_TABLE()
89};
90
91// `Main program' equivalent, creating windows and returning main app frame
92bool MyApp::OnInit()
93{
94 // Create the main frame window
9a83f860 95 MyFrame *frame = new MyFrame(NULL, wxT("Fractal Mountains for wxWidgets"), wxDefaultPosition, wxSize(640, 480));
025e88c5
JS
96
97 // Make a menubar
98 wxMenu *file_menu = new wxMenu;
5d2ac6b8 99 file_menu->Append(wxID_EXIT, wxGetStockLabel(wxID_EXIT));
025e88c5 100 menuBar = new wxMenuBar;
9a83f860 101 menuBar->Append(file_menu, wxT("&File"));
025e88c5
JS
102 frame->SetMenuBar(menuBar);
103
104 int width, height;
105 frame->GetClientSize(&width, &height);
106
107 (void) new MyCanvas(frame);
108
109 // Show the frame
e0e31ccd 110 frame->Show(true);
025e88c5 111
e0e31ccd 112 return true;
025e88c5
JS
113}
114
115BEGIN_EVENT_TABLE(MyFrame, wxFrame)
116 EVT_CLOSE(MyFrame::OnCloseWindow)
117 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
118END_EVENT_TABLE()
119
120// My frame constructor
121MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size):
e0e31ccd 122 wxFrame(frame, wxID_ANY, title, pos, size, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE )
025e88c5
JS
123{
124}
125
126// Intercept menu commands
babd36de 127void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
025e88c5
JS
128{
129 this->Destroy();
130}
131
babd36de 132void MyFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
025e88c5 133{
e0e31ccd 134 static bool destroyed = false;
025e88c5
JS
135 if (destroyed)
136 return;
137
138 this->Destroy();
139
e0e31ccd 140 destroyed = true;
025e88c5
JS
141}
142
143BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
144 EVT_PAINT(MyCanvas::OnPaint)
145END_EVENT_TABLE()
146
147// Define a constructor for my canvas
148MyCanvas::MyCanvas(wxFrame *frame):
e0e31ccd 149 wxWindow(frame, wxID_ANY)
025e88c5
JS
150{
151 wxColour wxCol1(255,255,255);
152 SnowPen = wxPen(wxCol1, 2, wxSOLID);
153
154 wxColour wxCol2(128,0,0);
155 MtnPen = wxPen(wxCol2, 1, wxSOLID);
156
157 wxColour wxCol3(0,128,0);
158 GreenPen = wxPen(wxCol3, 1, wxSOLID);
159
160 wxColour wxCol4(0,0,128);
161 WaterBrush = wxBrush(wxCol4, wxSOLID);
162}
163
babd36de 164void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
025e88c5
JS
165{
166 wxPaintDC dc(this);
e0e31ccd
WS
167 PrepareDC(dc);
168 Draw(dc);
025e88c5
JS
169}
170
171void MyCanvas::Draw(wxDC& dc)
172{
173 if (running) return;
b713f891 174
e0e31ccd
WS
175 running = true;
176 menuBar->EnableTop(0, false);
177
178 Randomize();
025e88c5 179
e0e31ccd
WS
180 dc.SetBackground(*wxLIGHT_GREY_BRUSH);
181 dc.Clear();
025e88c5 182
e0e31ccd
WS
183 int Left, Top, Right, Bottom;
184 GetClientSize(&Right, &Bottom);
025e88c5 185
e0e31ccd
WS
186 Right *= 3; Right /= 4;
187 Bottom *= 3; Bottom /= 4;
188 Left = 0;
189 Top = Bottom/8;
025e88c5 190
e0e31ccd
WS
191 wxPoint Water[4];
192 Water[0].x = Left; Water[0].y = Top;
193 Water[1].x = Right; Water[1].y = Top;
194 Water[2].x = Right+Bottom/2; Water[2].y = Bottom;
195 Water[3].x = Bottom/2; Water[3].y = Bottom;
025e88c5 196
e0e31ccd
WS
197 dc.SetBrush(WaterBrush);
198 dc.DrawPolygon(4, Water);
025e88c5 199
e0e31ccd
WS
200 double H = 0.75;
201 double Scale = Bottom;
202 double Ratio = 1.0 / pow(2.0, H);
203 double Std = Scale * Ratio;
204 Sealevel = Random(18) - 8;
025e88c5 205
e0e31ccd 206 Fractal(dc, Left, Top, Right, Bottom, 0, 0, 0, 0, detail, Std, Ratio);
025e88c5 207
e0e31ccd
WS
208 menuBar->EnableTop(0, true);
209 running = false;
025e88c5
JS
210}
211
212void 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)
213{
e0e31ccd
WS
214 int Xmid = (X1 + X2) / 2;
215 int Ymid = (Y1 + Y2) / 2;
216 int Z23 = (Z2 + Z3) / 2;
217 int Z41 = (Z4 + Z1) / 2;
218 int Newz = (int)((Z1 + Z2 + Z3 + Z4) / 4 + (double)(Random(17) - 8) / 8.0 * Std);
219
220 if (--Iteration)
221 {
222 int Z12 = (Z1 + Z2) / 2;
223 int Z34 = (Z3 + Z4) / 2;
224 double Stdmid = Std * Ratio;
225
226 Fractal(dc, Xmid, Y1, X2, Ymid, Z12, Z2, Z23, Newz, Iteration, Stdmid, Ratio);
227 Fractal(dc, X1, Y1, Xmid, Ymid, Z1, Z12, Newz, Z41, Iteration, Stdmid, Ratio);
228 Fractal(dc, Xmid, Ymid, X2, Y2, Newz, Z23, Z3, Z34, Iteration, Stdmid, Ratio);
229 Fractal(dc, X1, Ymid, Xmid, Y2, Z41, Newz, Z34, Z4, Iteration, Stdmid, Ratio);
230 }
231 else
232 {
233 if (Newz <= Sealevel)
234 {
235 wxPoint P[4];
236 P[0].x = Y1 / 2 + X1; P[0].y = Y1 + Z1;
237 P[1].x = Y1 / 2 + X2; P[1].y = Y1 + Z2;
238 P[2].x = Y2 / 2 + X2; P[2].y = Y2 + Z3;
239 P[3].x = Y2 / 2 + X1; P[3].y = Y2 + Z4;
240
241 dc.SetPen(* wxBLACK_PEN);
242 dc.SetBrush(* wxBLACK_BRUSH);
243
244 dc.DrawPolygon(4, P);
245
246 if (Z1 >= -(60+Random(25)))
247 dc.SetPen(GreenPen);
248 else if (Z1 >= -(100+Random(25)))
249 dc.SetPen(MtnPen);
250 else
251 dc.SetPen(SnowPen);
252
253 dc.DrawLine(Ymid/2+X2, Ymid+Z23, Ymid/2+X1, Ymid+Z41);
254 }
255 }
025e88c5
JS
256}
257