//--------------------------------------------------------------------------------------------------
//数学模型小作业(植物生长模型-初步模型)
//题目描述:
//01.参考书目:ISBN 7-309-04306-5.
//01.植物生长主要依靠:碳(C)和氮(N)两种元素.
//02.碳(C)主要由大气提供,通过光合作用由叶片吸收;氮(N)主要由土壤提供,通过植物的根部吸收.
//03.植物吸收这些元素,在植物体内输送,结合导致植物生长,这一过程机理尚未完全研究清楚,现在只能作简化的近似研究.
//04.通过长期的观察,可以确认以下几个基本假设:
//05. a.碳(C)由叶吸收,氮(N)由根吸收.
//06. b.特定植物对碳(C)和氮(N)的需求大致有一个固定的比例.
//07. c.碳(C)由叶吸收,也可从叶部输送至根部;氮(N)由根吸收,也可从根部输送到叶部.
//08. d.植物生长每一时刻补充的元素数量依赖于:碳(C)的数量与叶部尺寸有关;氮(N)的数量与根部尺寸有关.
//09. e.植物生长过程中,叶部尺寸和根部尺寸维持着某种均衡关系.
//[简化假设1]-------------------------------------------------------------------------------------------------
//10.如果不区分植物的根部和叶部,也不分碳(C)和氮(N);笼统的认为植物吸收养料而长大.
//11.假设植物吸收的养料与植物的体积成正比.则:dW/dt=k*V.
//12.其中:W-植物的质量,(单位:kg).W(t)-随时间变化的量.
// V-植物的体积,(单位:kg/m^3).V(t)-随时间变化的量.
// k-比例系数,与可供给的养料有关,也与能量转化的比例有关;假设为正的常数.
//13.假设植物的密度为ρ,且生长过程中ρ为常数,则可以得到:dW/dt=k*V=k*W/ρ=(k/ρ)*W.
//14.上面的方程称为生长方程,其解为:W(t)=W0*exp[(k/ρ)*t].
//15.其中:W0-初始时刻(t=0)时植物的质量.
//16.模型缺点:指数函数,植物随时间的增长无限增大,不符合实际.
//[简化假设2]-------------------------------------------------------------------------------------------------
//17.事实上随着植物的增长,维持结构稳定的能量比例增加了,将分子转化为组织的能量比例减少了,植物的生长减缓.
//18.为了对应这个假设,将原先设为常数的比例系数k,假设为变量k1,k1=a-b*W.其中:a,b为正的常数.
//19.则生长方程化为:dW/dt=k1*V=(a-b*W)*(W/ρ).
//20.引进中间变量:k2=a/ρ,Wm=k2*ρ/b,则:dW/dt=k2*W*(1-W/Wm).
//21.若初值为W0,则微分方程的解为:W(t)=Wm/[1-(1-Wm/W0)*exp(-k2*t)].
//21.观察方程可得:W(t)是时间t的单调增加函数,当t->∞,W(t)->Wm;即Wm是植物的极大质量;这个模型近似符合要求.
//------------------------------------------------------------------------------------------------------------
//程序编制要求(根据第2个近似模型):
//1.初始质量W0,密度ρ,常数a,常数b,交互读取.
//2.计算极限质量Wm,近似到达极限质量的时间.
//3.绘制时间植物质量示意图.
//--------------------------------------------------------------------------------------------------------------------
#include //包含Easyx模拟TC的BGI绘图库头文件
#include //包含数学运算头文件
#include //
#define DD 40//宏定义标题边框距离
#define DW 10//宏定义宽度边框距离
#define DH 10//宏定义高度边框距离
#define DC 200//宏定义控件区域宽度
#define nx 10//宏定义x轴刻度数量
#define ny 10//宏定义y轴刻度数量
#define PI 3.1415926//宏定义圆周率
//辅助颜色------------------------------------------
#define c1 RGB(38,47,86)//宏定义辅助线颜色1
#define c2 RGB(38,47,86)//宏定义辅助线颜色2
#define c3 RGB(255,255,255)//宏定义文字及边框颜色
#define c4 RGB(255,255,0)//颜色4
#define c5 RGB(0,255,255)//颜色5
#define c6 RGB(0,255,0)//颜色6
//曲线颜色------------------------------------------
#define cc1 RGB(0,255,0)//宏定义曲线颜色4(青色)
#define cc2 RGB(0,255,255)//宏定义曲线颜色2(绿色)
#define cc3 RGB(150,100,0)//宏定义曲线颜色3(黄色)
#define cc4 RGB(0,255,100)//宏定义曲线颜色1(红色)
#define cc5 RGB(255,100,0)//宏定义曲线颜色5(青色)
//定义结构体-------------------------------------------------------------------------------------------------------
typedef struct points
{
double x,y;//定义双精度变量
}DPOINT;//结束结构体
//窗口全局变量-----------------------------------------------------------------------------------------------------
int W = GetSystemMetrics(SM_CXSCREEN);//获取整个屏幕右下角X坐标
int H = GetSystemMetrics(SM_CYSCREEN);//屏幕Y坐标
int c_h=36;//定义控件高度
//数据全局变量
char is1[20]="0.3";//预定义:1.初始质量W0(kg)
char is2[20]="100";//2.密度ρ(Kg/m^3)
char is3[20]="0.3";//3.常系数a
char is4[20]="0.1";//4.常系数b
char is8[20]="450";//8.输入时间(h)
char is5[20],is6[20],is7[20],is9[20];//定义字符数组(存储字符串)
double d1,d2,d3,d4,d5,d6,d7,d8,d9;//(存储计算值)
int i,j,k;//
double value;//定义双精度变量
char stt[10];//定义字符数组
//函数声明---------------------------------------------------------------------------------------------------------
void sub_frame();//绘制框架子函数
void sub_calculate();//计算数据子函数
void func_W1(double Wm,double W0,double tt,double *Wt);//根据时间植物重量
//主函数-----------------------------------------------------------------------------------------------------------
void main()
{
sub_frame();//绘图初始化
MOUSEMSG m;//定义鼠标消息
while(true)//循环
{
m=GetMouseMsg();//获取一条鼠标消息
switch(m.uMsg)//根据获得的消息选择分支
{
case WM_LBUTTONDOWN://鼠标左键单击时判断数据输入
{
//判断鼠标位置是否在指定的控件区域
//A.获取原始数据(横坐标在输入区域时输入数据)-------------------------------
if(m.x>=W-DW-DC && m.x<=W-DW)
{
//1.初始质量W0(kg):-----------------------------------------------------
if(m.y>=H-DH-16*c_h+1 && m.y<=H-DH-15*c_h-1)//
{
InputBox(is1,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-16*c_h+1,W-DW,H-DH-15*c_h);
outtextxy(W-DW-DC+DC/2+15,H-DH-16*c_h+15,is1);//写控件字符串
}//结束if
//2.密度ρ(Kg/m^3):-----------------------------------------------------
if(m.y>=H-DH-15*c_h+1 && m.y<=H-DH-14*c_h-1)//
{
InputBox(is2,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-15*c_h+1,W-DW,H-DH-14*c_h);
outtextxy(W-DW-DC+DC/2+15,H-DH-15*c_h+15,is2);//写控件字符串
}//结束if
//3.常系数a:-----------------------------------------------------
if(m.y>=H-DH-14*c_h+1 && m.y<=H-DH-13*c_h-1)//
{
InputBox(is3,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-14*c_h+1,W-DW,H-DH-13*c_h);
outtextxy(W-DW-DC+DC/2+15,H-DH-14*c_h+15,is3);//写控件字符串
}//结束if
//4.常系数b:-----------------------------------------------------
if(m.y>=H-DH-13*c_h+1 && m.y<=H-DH-12*c_h-1)//
{
InputBox(is4,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-13*c_h+1,W-DW,H-DH-12*c_h);
outtextxy(W-DW-DC+DC/2+15,H-DH-13*c_h+15,is4);//写控件字符串
}//结束if
//8.输入时间(h):-----------------------------------------------------
if(m.y>=H-DH-9*c_h+1 && m.y<=H-DH-8*c_h-1)//
{
InputBox(is8,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-9*c_h+1,W-DW,H-DH-8*c_h);
outtextxy(W-DW-DC+DC/2+15,H-DH-9*c_h+15,is8);//写控件字符串
}//结束if
}//结束if(横坐标在输入区域时输入数据)
sub_frame();//重绘框架
//B.计算并绘图(横坐标在绘图区域时计算绘图)---------------------------------
if(m.x>=DW && m.x<=W-DW-DC)
{
sub_calculate();//调用计算绘图函数
}//结束if
break;//
}//结束case(结束鼠标左键单击事件消息处理)
case WM_RBUTTONDOWN://鼠标移动的时候画个空心的圆
return;//返回while
}//结束switch(结束鼠标消息)
}//结束while
}//结束主函数
//绘制框架子函数
void sub_frame()
{
//1.全屏效果---------------------------------------------------------------------------
initgraph(W,H);//初始化绘图窗口
HWND hWnd = GetHWnd();//获取窗口句柄
LONG style = GetWindowLong(hWnd,-16);//获得窗口风格
style = style & ~WS_CAPTION & ~WS_SIZEBOX; //窗口全屏显示且不可改变大小
SetWindowLong(hWnd,-16,style);//设置窗口风格
SetWindowPos(hWnd, NULL,0,0,W,H,SWP_NOZORDER);//改变窗口位置,尺寸和Z序
//ShowCursor(FALSE);//显示时隐藏鼠标
//------------------------------------------------------------------------------------
//2.绘制工作区边框
setcolor(c3);
rectangle(DW,DD,W-DW,H-DH);//外边框
rectangle(W-DW-DC,DD,W-DW,H-DH);//控件区域边框
//5.输出标题
setfont(16,0,"黑体");
outtextxy(5,10,"数学模型小作业(植物生长模型-初步模型)");
//6.输出简单说明
RECT r={W-DW-DC+10,DD+10,W-DW-10,H-DH-10};//
setfont(12,0,"宋体");//
drawtext("数学模型小作业:\n \n \
植物生长模型-初步模型\
\
\n\n\
操作说明:\n\n\
鼠标左键 : 数据输入\n\
鼠标右键 : 退出程序\n\
\n\
1~4为输入数据 5~9为计算数据\n\
\n\n\
\n\n\
\
\n", &r, DT_WORDBREAK);//
//7.调整说明文字下面的矩形控件
int c_x1=W-DW-DC,c_x2=W-DW;//控件左右x坐标
int c_y1=H-DH;//第1个控件下y坐标
for(int i=1;i<=16;i++)
{
rectangle(c_x1,c_y1,c_x2,c_y1-c_h);//
c_y1=c_y1-c_h;
}//结束for
//8.绘制控件说明文字
outtextxy(c_x1+10,H-DH-16*c_h+15,"1.初始质量W0(kg):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-15*c_h+15,"2.密度ρ(Kg/m^3):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-14*c_h+15,"3.常系数a:");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-13*c_h+15,"4.常系数b:");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-12*c_h+15,"5.中间变量k2:");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-11*c_h+15,"6.中间变量Wm(Kg):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-10*c_h+15,"7.近似收获时间(h):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-9*c_h+15,"8.输入时间(h):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-8*c_h+15,"9.植物重量W(Kg):");//输出字符串模拟控件文字
//8.初始化原始数据
outtextxy(W-DW-DC+DC/2+15,H-DH-16*c_h+15,is1);//写控件字符串
outtextxy(W-DW-DC+DC/2+15,H-DH-15*c_h+15,is2);//写控件字符串
outtextxy(W-DW-DC+DC/2+15,H-DH-14*c_h+15,is3);//写控件字符串
outtextxy(W-DW-DC+DC/2+15,H-DH-13*c_h+15,is4);//写控件字符串
outtextxy(W-DW-DC+DC/2+15,H-DH-9*c_h+15,is8);//写控件字符串
}//结束子程序
//计算数据子函数
void sub_calculate()
{
//1.原始数据转化为双精度数
d1=atof(is1);//1.初始质量W0(kg)
d2=atof(is2);//2.密度ρ(Kg/m^3)
d3=atof(is3);//3.常系数a
d4=atof(is4);//4.常系数b
d8=atof(is8);//8.输入时间(h)
//2.根据数据计算要求项目---------------------------------------------------------------------------
d5=1.0*d3/d2;//5.中间变量k2
d6=1.0*d3/d4;//6.中间变量Wm(Kg)
double d7a=(1.0*d6/d1-1.0);//中间变量
double d7b=0.01/d7a;//中间变量(剩余0.01时认为可以收获)
d7=0.0-1.0*log(d7b)/d5;//7.近似收获时间(h)
func_W1(d6,d1,d8,&d9);//9.植物重量W(Kg)
//3.将计算结果转化为字符串--------------------------------------------------------------------------
gcvt(d5,6,is5);//
gcvt(d6,6,is6);//
gcvt(d7,6,is7);//
gcvt(d9,6,is9);//
//4.将字符串写入控件中
setfillcolor(BLACK);
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-12*c_h+1,W-DW,H-DH-11*c_h);
outtextxy(W-DW-DC+DC/2+45,H-DH-12*c_h+15,is5);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-11*c_h+1,W-DW,H-DH-10*c_h);
outtextxy(W-DW-DC+DC/2+45,H-DH-11*c_h+15,is6);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-10*c_h+1,W-DW,H-DH-9*c_h);
outtextxy(W-DW-DC+DC/2+45,H-DH-10*c_h+15,is7);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-8*c_h+1,W-DW,H-DH-7*c_h);
outtextxy(W-DW-DC+DC/2+45,H-DH-8*c_h+15,is9);//写控件字符串
//------------------------------------------------------------
//5.绘制工作区坐标线
//画x轴刻度标线及文字(时间t)---------------------------
double xstep=(W-2*DW-DC)/(1.0*nx);//x方向步长(nx个刻度)(对应的绘图单位)
double ystep=(H-DH-DD)/(1.0*ny);//y方向步长(ny个刻度)(对应的绘图单位)
double x_scale=(W-2*DW-DC)*1.0/(1.0*d7);//每个数学单位x对应的屏幕单位
double y_scale=(H-DH-DD)*1.0/(1.0*d6);//重量
for(i=0;i<=nx;i++)
{
setcolor(c1);//竖直辅助线颜色
line(DW+xstep*i,H-DH,DW+xstep*i,DD);//画竖直小刻度线
setcolor(c3);//文字颜色
value=i*(d7)/(1.0*nx);//所在的刻度数值
gcvt(value,6,stt);//将浮点数value转换为字符串stt
outtextxy(DW+xstep*i-10,H-DH-20,stt);//在规定的位置放置字符串
}//结束for
//画y轴刻度标线及文字(植物重量)---------------------------
for(i=0;i<=ny;i++)
{
setcolor(c1);//水平辅助线颜色
line(DW,DD+ystep*i,W-DW-DC,DD+ystep*i);//画水平小刻度线
setcolor(c3);//文字颜色
value=(ny-i)*(1.0*d6)/ny;//所在的刻度数值
gcvt(value,5,stt);//将浮点数value转换为字符串stt
outtextxy(DW+15,DD+ystep*i-10,stt);//在规定的位置放置字符串
}//结束for
//6.重新绘制工作区边框
setcolor(c3);
rectangle(DW,DD,W-DW,H-DH);//外边框
rectangle(W-DW-DC,DD,W-DW,H-DH);//控件区域边框
//------------------------------------------------------------
//7.获取时刻变化时的植物重量变化曲线------------------------------------------------
double n1;//
DPOINT *p1;//1.重量
p1=new DPOINT[10000];//定义N1点表
for(int j=0;j<=d7;j++)//时间范围
{
double tt=j;//时刻
//1.重量n1--------------------------------
func_W1(d6,d1,tt,&n1);//根据时间植物重量
p1[j].x=DW+tt*x_scale;
p1[j].y=H-DH-n1*y_scale;
}//结束for
//8.绘制时刻变化时的速度位移变化曲线---------------------------------------------------
setcolor(cc1);//曲线颜色1
for(j=0;j<=d7-1;j++)//
{
line(p1[j].x,p1[j].y,p1[j+1].x,p1[j+1].y);//
}//结束for
setcolor(cc2);//曲线颜色2
double x1=DW+d8*x_scale;//
double y1=H-DH-d9*y_scale;//
line(x1-5,y1,x1+5,y1);//
line(x1,y1-5,x1,y1+5);//
line(DW,y1,x1-10,y1);//
line(x1,y1+10,x1,H-DH);//
}//结束子函数
void func_W1(double Wm,double W0,double tt,double *Wt)//根据时间植物重量
{
double WW=(1.0*Wm/W0)-1.0;//中间变量
*Wt=1.0*Wm/(1+WW*exp(0.0-d5*tt));//植物重量(Kg)
}//结束子函数
//*/
//--------------------------------------------------------------------------------------------------
数学模型小作业(植物生长模型-初步模型)