看到網上很多代碼繪製的櫻花樹,參見CSDN,便想自己試試,但是畫的有點醜
基本思路
其實就是一個“二叉樹的遍歷”的思路,使用遞歸不斷的二叉,就可以了,這也算是分形圖案了。但是簡單的遞歸二叉,不掌握好長度、角度、粗細以及主幹和枝幹的變化就會很規整。所以慢慢調參吧。
這裏採用的是給出每個參數的最大取值範圍,然後設置一個縮小的函數,隨着遞歸層數的提高,對應的參數越來越小,這個小的程度和範圍就要自己把握了。
縮小函數可以參考:
依賴
這裏的櫻花樹使用的是一個簡單的C++圖形庫 easyx,簡單容易上手。
演示
基礎代碼
#include <easyx.h>
#include <conio.h>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <cmath>
#include <iostream>
#define SEE(x) cout << #x << ":" << x << endl;
#define RED (RGB(240, 128, 128))
#define WHITE (RGB(255, 255, 255))
#define BROWN (RGB(160, 82, 45))
// 與主幹角度的偏移角度
const int angle_min = 18;
const int angle_max = 28;
// 長度
const int length_min = 60;
const int length_max = 90;
// 寬度
const int thick = 10;
// 繪製區大小
int width = 800, height = 600;
using namespace std;
typedef pair<int, int> Point;
// 繪製一條線
void drawline(Point st, Point ed) {
line(st.first, st.second, ed.first, ed.second);
}
// 產生範圍內的隨機數
int rand_range(int st, int ed) {
return st + rand() % (ed - st);
}
// 給點原點 相對於水平的角度 長度 返回處理後的節點
Point getPointFromAngle(Point src, float angle, int length) {
angle = 3.14/180.0 * angle;
return { src.first+length*cos(angle), src.second-length*sin(angle) };
}
// 遞歸畫叉
void draw_bifurcation(Point p, float angle, int layer) {
// 結束層
if (layer == 13) {
return;
}
srand(time(NULL));
// 偏移角
float delta = rand_range(angle_min, angle_max);
// 收縮 使用根號
float shrink = pow(layer, 0.5);
// 便宜的角度越來越小
float left_angle = angle + delta/shrink;
// 右分支的角度確定
float right_angle = left_angle - 2.4*delta/shrink;
// 隨機長度
int length_left = rand_range(length_min / shrink, length_max / shrink);
int length_right = rand_range(length_min / shrink, length_max / shrink);
// 獲取下一個分支點
Point left = getPointFromAngle(p, left_angle, length_left);
Point right = getPointFromAngle(p, right_angle, length_right);
// 末端繪製紅白相間的花瓣
int type = rand() % 2;
if (layer > 8) {
if (type == 0) {
setlinecolor(RED);
}
else {
setlinecolor(WHITE);
}
}
else {
setlinecolor(BROWN);
}
// 設置厚度
setlinestyle(PS_SOLID , thick/layer);
drawline(p, left);
// 遞歸左分支
draw_bifurcation(left, left_angle, layer + 1);
setlinestyle(PS_SOLID, thick / layer);
if (layer > 8) {
if (type == 0) {
setlinecolor(WHITE);
}
else {
setlinecolor(RED);
}
}
else {
setlinecolor(BROWN);
}
// 動態效果
Sleep(1);
drawline(p, right);
// 遞歸右分支
draw_bifurcation(right, right_angle, layer + 1);
}
// 隨機繪製地面的花瓣
void draw_ground() {
int left = width * 0;
int right = width * 1;
int up = height - 60;
int down = height;
int length = 4;
setlinecolor(RED);
setlinestyle(PS_SOLID, 3);
int x, y, angle;
for (int i = 0; i < 300; i++) {
x = rand_range(left, right);
y = rand_range(up, down);
angle = rand_range(0, 360);
Point ed = getPointFromAngle({ x, y }, angle, length);
Sleep(5);
drawline({ x, y }, ed);
}
}
int main() {
initgraph(width, height);
// 設置背景色
setbkcolor(RGB(241, 215, 118));
cleardevice();
// 繪製主幹
setlinecolor(BROWN);
setlinestyle(PS_SOLID | PS_ENDCAP_SQUARE, 10);
line(width/2, height-110, width/2, height-20);
// 遞歸繪製
draw_bifurcation({ width/2, height-110 }, 90.0, 1);
// 繪製掉落花瓣的地面
draw_ground();
_getch();
closegraph();
return 0;
}