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: fractal.cpp 35650 2005-09-23 12:56:45Z MR $ 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 26doesn't seem to be an equivalent of under wxWidgets, and my quick 27hack 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 49static int detail = 9; // CHANGE THIS... 7,8,9 etc 50 51static bool running = false; 52static wxMenuBar *menuBar = NULL; 53 54// Define a new application type 55class MyApp: public wxApp 56{ 57public: 58 bool OnInit(); 59}; 60 61IMPLEMENT_APP(MyApp) 62 63// Define a new frame type 64class MyFrame: public wxFrame 65{ 66public: 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 76class MyCanvas: public wxWindow 77{ 78public: 79 MyCanvas(wxFrame *frame); 80 void Draw(wxDC& dc); 81 82private: 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 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 96 MyFrame *frame = new MyFrame(NULL, _T("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, _T("&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 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): 123 wxFrame(frame, wxID_ANY, title, pos, size, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE ) 124{ 125} 126 127// Intercept menu commands 128void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event)) 129{ 130 this->Destroy(); 131} 132 133void 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 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): 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 165void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) 166{ 167 wxPaintDC dc(this); 168 PrepareDC(dc); 169 Draw(dc); 170} 171 172void 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 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{ 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 259