利用递归和分形绘制樱花树

本文介绍如何运用递归和分形原理来绘制逼真的樱花树。通过递归调用实现图形的自相似性,用粉色圆点模拟樱花花瓣,通过随机数控制生成过程,达到樱花树层次感和艺术效果。
摘要由CSDN通过智能技术生成

递归

一个函数直接或间接的调用自身的方法称为递归调用。

分形

分析图形具有如下特点:

  • 从形状整体上看,物体图形处处不规则。
  • 在较小的尺度上具有相似性。

樱花树

可以利用粉色填充圆代表樱花,为了使最终绘制的樱花树错落有致,可以在生成时利用随机值控制生成的过程。

// 樱花树的绘制.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <graphics.h>
#include <conio.h>
#include <math.h>
#include <stdio.h>
#include <time.h>


const double PI = 3.1415926;
const int canvas_width = 1000;
const int canvas_height = 600;
double tree_angle = PI / 6;
double tree_rate = 0.6;

//确定是否选择展示绘图过程
int if_show_animation = 1;

//将指定范围的值映射到另外一个范围中
double map_value(double input,double input_min, double input_max, double output_min, double output_max)
{
    double output;
    if (fabs(input - input_min) < 0.0000) output = output_min;
    else output = (input - input_min) * (output_max - output_min) / (input_max - input_min) + output_min;
    return output;
}

//生成随机数
double num_rand(double num_min, double num_max )
{
    srand(time(NULL));
    int N = 999;//确定生成随机数的精度,三位数决定随机数的精度是三位的
    double t = rand() % (N + 1) / (double)(N + 1);
    double num_r = map_value(t, 0, 1, num_min, num_max);
    return num_r;
}

//枝干的生成和绘制函数
void brunch(double x_start, double y_start, double t_length, double t_angle, double t_thickness, double t_generation)
{
    //坐标的计算
    double x_end = x_start + t_length * cos(t_angle);
    double y_end = y_start + t_length * sin(t_angle);

    //枝干的属性设置
    setlinestyle(PS_SOLID, t_thickness);
    COLORREF t_color = HSVtoRGB(15, 0.75, 0.4 + t_generation * 0.05);
    setlinecolor(t_color);
    //绘制当前枝干
    line(x_start, y_start, x_end, y_end);

    //子枝干的绘制
    int child_generation = t_generation + 1;//枝干代数
    double child_length = tree_rate * t_length;
    double left_child_length = child_length * num_rand(0.9, 1.1);
    double right_child_length = child_length * num_rand(0.9, 1.1);
    double center_child_length = child_length * num_rand(0.8, 1.1);

    //利用递归生成子枝干
    if (child_length >= 2 && child_generation < 20)
    {
        double child_thickness= t_thickness*0.8;
        if (child_thickness < 2) child_thickness = 2;
        if (num_rand(0, 1) < 0.95)
        {
            brunch(x_end, y_end, left_child_length, t_angle + tree_angle * num_rand(0.4, 0.9), child_thickness, child_generation);
        }
        if (num_rand(0, 1) < 0.95)
        {
            brunch(x_end, y_end, right_child_length, t_angle - tree_angle * num_rand(0.4, 0.9), child_thickness, child_generation);
        }
        if (num_rand(0, 1) < 0.85)
        {
            brunch(x_end, y_end, center_child_length, t_angle + tree_angle * num_rand(-1, 1), child_thickness, child_generation);
        }
    }
    //绘制樱花
    else
    {
        setlinestyle(PS_SOLID, 1);
        COLORREF f_color = RGB(num_rand(0,255),num_rand(0,230), num_rand(0, 250));
        setlinecolor(f_color);
        setfillcolor(f_color);
        if (child_length <= 4)
        {
            fillcircle(x_end, y_end, 2);
            fillcircle(x_end, y_end, 2);
        }
        else
        {
            fillcircle(x_end, y_end, child_length / 3);
        }
    }
    if (if_show_animation)
    {
        FlushBatchDraw();
        //Sleep(5);
    }


}
void t_initial()
{
    srand(time(0));
    initgraph(canvas_width, canvas_height);
    setbkcolor(0xFFFFFF);
    cleardevice();
    BeginBatchDraw();
    brunch(canvas_width / 2, canvas_height,0.5 * canvas_height * tree_rate, -PI / 2, 15 * tree_rate, 1);
    FlushBatchDraw();
}
void t_update()
{
    MOUSEMSG m;// 保存鼠标
    if (MouseHit())//判断鼠标是否点击
    {
        m = GetMouseMsg();
        if (m.uMsg == WM_MOUSEMOVE)
        {
            tree_angle = map_value(m.x, 0, canvas_width, PI / 10, PI / 4);
            tree_angle = map_value(m.y, 0, canvas_height, 0.8, 0.4);
        }
        if (m.uMsg == WM_LBUTTONDOWN)//左键画图
        {
            cleardevice();
            brunch(canvas_width / 2, canvas_height, 0.5 * canvas_height * tree_rate, -PI / 2, 15 * tree_rate, 1);
            FlushBatchDraw();
        }
        if (m.uMsg == WM_RBUTTONDOWN)//右键改变是否显示过程
        {
            if_show_animation = -if_show_animation;
        }
    }
}
int main()
{
    t_initial();
    while (1)
    {
        t_update();
    }
    return 0;
}


当然也可以设置成自己想要的颜色
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CCC_bi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值