//--------------------------------------------------------------------------------------------------------------------
//数学模型小作业(风帆动力模型)
//题目描述:
//01.参考书目:ISBN 7-309-01752-8.
//01.在风帆时代,远洋航行不可能全部顺风航行;如何在逆风航行到目的地,是本模型考虑的问题.
//02.为了讨论方便,模型作了如下简化假设:
//03.a.行驶的动力全部依靠风帆,没有额外的动力.
//04.b.风对风帆和船体的动力和阻力都只与迎风面积有关,且都为常数k.
//05.c.在航速不大的情况下,假设航速与净推力成正比,记为常数k1.
//06.d.假设船行驶方向与迎风方向夹角为θ,风帆与船行驶方向夹角为α,S1,S2为风帆和船体的迎风面积.
//07.基于以上假设对船体做受力分析:
//08. a.对船体而言,受到的风力:p=k*S2.
//09. b.分解为沿船行驶方向的阻力:p1=p*cos(θ).
//10. c.分解为垂直于船行驶方向的阻力:p2=p*sin(θ).(可被船舵抵消,不予考虑)
//11. d.对风帆而言,受到的风力:W=k*S1.
//12. e.分解为平行于帆面的动力:W2=W*cos(θ-α).(与帆面平行,可以忽略)
//13. f.分解为垂直于帆面的动力:W1=W*sin(θ-α).
//14. g.W1分解为沿船行驶方向的动力:f1=W1*sin(α)=W*sin(θ-α)*sin(α)=0.5*W*[cos(θ-2α)-cos(θ)].
//15. h.W1分解为垂直船行驶方向的阻力:f2=W1*cos(α).(可被船舵抵消,不予考虑)
//16. i.由风力引起的航行动力的合力为:f1-p1.
//17.对船体做动力分析:
//18. a.沿行驶方向的速度:v=k1*(f1-p1).
//19. b.沿迎风方向的速度分量:v1=v*cos(θ)=k1*(f1-p1)*cos(θ).
//20. c.当行驶方向一定时,θ为常数,求得风帆角度α,使得航速v1最大;对f1求导,得到α=θ/2.
//21. d.求得最大速度:v1=(k1*W/2)*[1-(1+2*p/W)*cos(θ)]*cos(θ).
//22. e.取中间变量:k2=(k1*W/2),t=(1+2*p/W)=(1+2*S2/S1).
//23. f.简化后的方程为:v1=k2*t*[1/(4*t*t)-(cos(θ)-1/2t)^2].
//24.动力分析的讨论:
//25. a.为满足v1>0,0<cos(θ)<(1/t),即acos(1/t)<θ<90.(超过这个范围即不可能迎风行驶).
//26. b.当cos(θ)=(1/2t)时,迎风速度v1最大.此时v1=k2/(4t).
//26. c.达到一定位移后,走折线,调整航向和风帆角度,迂回行驶到迎风方向目的地.
//程序编制要求:
//1.风帆迎风面积S1,船体迎风面积S2,风力系数k,推力速度系数k1,交互读取.
//2.计算满足最大速度v1的角度θ,α,v1.
//3.绘制在容许角度范围内的速度变化曲线.
//--------------------------------------------------------------------------------------------------------------------
#include <graphics.h>//包含Easyx模拟TC的BGI绘图库头文件
#include <math.h>//包含数学运算头文件
#include <iostream.h>//
#define DD 40//宏定义标题边框距离
#define DW 10//宏定义宽度边框距离
#define DH 10//宏定义高度边框距离
#define DC 200//宏定义控件区域宽度
#define nx 10//宏定义x轴刻度数量
#define ny 15//宏定义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 cc1 RGB(255,0,0)//宏定义曲线颜色1(红色)
#define cc2 RGB(0,255,0)//宏定义曲线颜色2(绿色)
#define cc3 RGB(255,255,0)//宏定义曲线颜色3(黄色)
//定义结构体-------------------------------------------------------------------------------------------------------
typedef struct points
{
double x,y;//定义双精度变量
}DPOINT;//结束结构体
//定义全局变量-----------------------------------------------------------------------------------------------------
int W = GetSystemMetrics(SM_CXSCREEN);//获取整个屏幕右下角X坐标
int H = GetSystemMetrics(SM_CYSCREEN);//屏幕Y坐标
char is1[20]="10.0";//预定义:1.船体迎风面积S2(m^2)
char is2[20]="100.0";//2.风帆迎风面积S1(m^2)
char is3[20]="100.0";//3.风力系数k(N/m^2)
char is4[20]="0.001";//4.推力系数k1(m/s*N)
char is5[20]="100.0";//5.输入距离(m)
char is12[20]="80.0";//12.输入角度xi(°)
char is6[20],is7[20],is8[20],is9[20],is10[20],is11[20],is13[20],is14[20],is15[20],is16[20];//定义字符数组(存储字符串)
double d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16;//定义双精度变量(存储计算值)
double i=0,j=0,k=0;//
//函数声明---------------------------------------------------------------------------------------------------------
void sub_frame();//绘制框架子函数
void sub_calculate();//计算数据子函数
void func_xi_v(double k2,double tt,double xi,double *v);//根据角度求速度
//主函数-----------------------------------------------------------------------------------------------------------
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.船体迎风面积S2(m^2):-----------------------------------------------------
if(m.y>=H-DH-16*36+1 && m.y<=H-DH-15*36-1)//
{
InputBox(is1,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-16*36+1,W-DW,H-DH-15*36);
outtextxy(W-DW-DC+DC/2+15,H-DH-16*36+15,is1);//写控件字符串
}//结束if
//2.风帆迎风面积S1(m^2):-----------------------------------------------------
if(m.y>=H-DH-15*36+1 && m.y<=H-DH-14*36-1)//
{
InputBox(is2,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-15*36+1,W-DW,H-DH-14*36);
outtextxy(W-DW-DC+DC/2+15,H-DH-15*36+15,is2);//写控件字符串
}//结束if
//3.风力系数k(N/m^2):-----------------------------------------------
if(m.y>=H-DH-14*36+1 && m.y<=H-DH-13*36-1)//
{
InputBox(is3,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-14*36+1,W-DW,H-DH-13*36);
outtextxy(W-DW-DC+DC/2+15,H-DH-14*36+15,is3);//写控件字符串
}//结束if
//4.推力系数k1(m/s*N):-----------------------------------------------
if(m.y>=H-DH-13*36+1 && m.y<=H-DH-12*36-1)//
{
InputBox(is4,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-13*36+1,W-DW,H-DH-12*36);
outtextxy(W-DW-DC+DC/2+15,H-DH-13*36+15,is4);//写控件字符串
}//结束if
//5.输入距离(m):-----------------------------------------------
if(m.y>=H-DH-12*36+1 && m.y<=H-DH-11*36-1)//
{
InputBox(is5,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-12*36+1,W-DW,H-DH-11*36);
outtextxy(W-DW-DC+DC/2+15,H-DH-12*36+15,is5);//写控件字符串
}//结束if
//12.输入角度xi(°):-----------------------------------------------------
if(m.y>=H-DH-5*36+1 && m.y<=H-DH-4*36-1)//
{
InputBox(is12,9,"请输入数据");//读入数据
setfillcolor(BLACK);
fillrectangle(W-DW-DC+DC/2+10,H-DH-5*36+1,W-DW,H-DH-4*36);
outtextxy(W-DW-DC+DC/2+15,H-DH-5*36+15,is12);//写控件字符串
}//结束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);//控件区域边框
//3.输出标题
setfont(16,0,"黑体");
outtextxy(5,10,"数学模型小作业(风帆动力模型)");
//4.输出简单说明
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~5为输入数据 6~16为计算数据\n\
\n\n\
\n\n\
\
\n", &r, DT_WORDBREAK);//
//5.调整说明文字下面的矩形控件
int c_h=36;//定义控件高度
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
//6.绘制控件说明文字
outtextxy(c_x1+10,H-DH-16*c_h+15,"1.船体迎风面积S2(m^2):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-15*c_h+15,"2.风帆迎风面积S1(m^2):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-14*c_h+15,"3.风力系数k(N/m^2):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-13*c_h+15,"4.推力系数k1(m/s*N):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-12*c_h+15,"5.输入距离(m):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-11*c_h+15,"6.最小角度θ0(°):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-10*c_h+15,"7.最佳角度θ(°):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-9*c_h+15,"8.径向速度v1(m/s):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-8*c_h+15,"9.切向速度v2(m/s):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-7*c_h+15,"10.合成速度v(m/s):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-6*c_h+15,"11.到达时间(s):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-5*c_h+15,"12.输入角度xi(°):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-4*c_h+15,"13.径向速度v1(m/s):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-3*c_h+15,"14.切向速度v2(m/s):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-2*c_h+15,"15.合成速度v(m/s):");//输出字符串模拟控件文字
outtextxy(c_x1+10,H-DH-1*c_h+15,"16.到达时间(s):");//输出字符串模拟控件文字
//7.初始化原始数据
outtextxy(W-DW-DC+DC/2+60,H-DH-16*36+15,is1);//写控件字符串
outtextxy(W-DW-DC+DC/2+60,H-DH-15*36+15,is2);//写控件字符串
outtextxy(W-DW-DC+DC/2+60,H-DH-14*36+15,is3);//写控件字符串
outtextxy(W-DW-DC+DC/2+60,H-DH-13*36+15,is4);//写控件字符串
outtextxy(W-DW-DC+DC/2+60,H-DH-12*36+15,is5);//写控件字符串
outtextxy(W-DW-DC+DC/2+60,H-DH-5*36+15,is12);//写控件字符串
}//结束子程序
//计算数据子函数
void sub_calculate()
{
//1.原始数据转化为双精度数
d1=atof(is1);//1.船体迎风面积S2(m^2)
d2=atof(is2);//2.风帆迎风面积S1(m^2)
d3=atof(is3);//3.风力系数k(N/m^2)
d4=atof(is4);//4.推力系数k1(m/s*N)
d5=atof(is5);//5.输入距离(m)
d12=atof(is12);//12.输入角度xi(°)
//2.根据数据计算要求项目---------------------------------------------------------------------------
double w=d3*d2;//风力W=k*s1
double k2=d4*w*0.5;//中间变量k2=(k1*W/2)
double tt=1+(2.0*d1)/d2;//中间变量t=(1+2*p/W)=(1+2*S2/S1)
double d6r=acos(1.0/(1.0*tt));//最小角度θ0(弧度)
d6=d6r*180.0/PI;//6.最小角度θ0(°)
double d7r=acos(1.0/(2.0*tt));//最佳角度θ(弧度)
d7=d7r*180.0/PI;//7.最佳角度θ(°)
d8=k2/(4.0*tt);//8.径向速度v1(m/s)
d10=d8/(1.0*cos(d7r));//10.合成速度v(m/s)
d9=d10*sin(d7r);//9.切向速度v2(m/s)
d11=d5/(1.0*d8);//11.到达时间(s)
double d12r=d12*PI/180.0;//12.输入角度xi(弧度)
func_xi_v(k2,tt,d12r,&d13);//13.径向速度v1(m/s)
d15=d13/(1.0*cos(d12r));//15.合成速度v(m/s)
d14=d15*sin(d12r);//14.切向速度v2(m/s)
d16=d5/(1.0*d13);//16.到达时间(s)
//3.将计算结果转化为字符串--------------------------------------------------------------------------
gcvt(d6,6,is6);//
gcvt(d7,6,is7);//
gcvt(d8,6,is8);//
gcvt(d9,6,is9);//
gcvt(d10,6,is10);//
gcvt(d11,6,is11);//
gcvt(d13,6,is13);//
gcvt(d14,6,is14);//
gcvt(d15,6,is15);//
gcvt(d16,6,is16);//
//4.绘制工作区坐标线
//画x1轴刻度标线及文字---------------------------
double value;//定义双精度变量
char stt[10];//定义字符数组
double xstep=(W-2*DW-DC)/(1.0*nx);//x方向步长(nx个刻度)(对应的绘图单位)
double ystep=(H-DH-DD)/(1.0*ny);//y方向步长(ny个刻度)(对应的绘图单位)
for(int i=0;i<=nx;i++)
{
setcolor(c1);//竖直辅助线颜色
line(DW+xstep*i,H-DH,DW+xstep*i,DD);//画竖直小刻度线
setcolor(c3);//文字颜色
value=d6+xstep*i*(90.0-d6)/(W-2*DW-DC);//所在的刻度数值
gcvt(value,5,stt);//将浮点数value转换为字符串stt
outtextxy(DW+xstep*i-10,H-DH-20,stt);//在规定的位置放置字符串
}//结束for
//画y1轴刻度标线及文字---------------------------
for(i=0;i<=ny;i++)
{
setcolor(c2);//水平辅助线颜色
line(DW,DD+ystep*i,W-DW-DC,DD+ystep*i);//画水平小刻度线
setcolor(cc1);//文字颜色
value=ystep*(ny-i)*(1.0*d8)/(H-DH-DD);//所在的刻度数值
gcvt(value,3,stt);//将浮点数value转换为字符串stt
outtextxy(DW+15,DD+ystep*i+5,stt);//在规定的位置放置字符串
}//结束for
//画y2轴刻度标线及文字---------------------------
for(i=0;i<=ny;i++)
{
setcolor(c2);//水平辅助线颜色
line(DW,DD+ystep*i,W-DW-DC,DD+ystep*i);//画水平小刻度线
setcolor(cc2);//文字颜色
value=ystep*(ny-i)*(2.0*d10)/(H-DH-DD);//所在的刻度数值
gcvt(value,3,stt);//将浮点数value转换为字符串stt
outtextxy(W-DW-DC-30,DD+ystep*i+5,stt);//在规定的位置放置字符串
}//结束for
//5.重新绘制工作区边框
setcolor(c3);
rectangle(DW,DD,W-DW,H-DH);//外边框
rectangle(W-DW-DC,DD,W-DW,H-DH);//控件区域边框
//6.将字符串写入控件中
setfillcolor(BLACK);
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-11*36+1,W-DW,H-DH-10*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-11*36+15,is6);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-10*36+1,W-DW,H-DH-9*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-10*36+15,is7);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-9*36+1,W-DW,H-DH-8*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-9*36+15,is8);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-8*36+1,W-DW,H-DH-7*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-8*36+15,is9);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-7*36+1,W-DW,H-DH-6*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-7*36+15,is10);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-6*36+1,W-DW,H-DH-5*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-6*36+15,is11);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-4*36+1,W-DW,H-DH-3*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-4*36+15,is13);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-3*36+1,W-DW,H-DH-2*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-3*36+15,is14);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-2*36+1,W-DW,H-DH-1*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-2*36+15,is15);//写控件字符串
//------------------------------------------------------------
fillrectangle(W-DW-DC+DC/2+40,H-DH-1*36+1,W-DW,H-DH-0*36);
outtextxy(W-DW-DC+DC/2+45,H-DH-1*36+15,is16);//写控件字符串
//------------------------------------------------------------
setcolor(cc1);//说明曲线颜色
line(W-DW-DC-200,H-DH-4*36+18,W-DW-DC-260,H-DH-4*36+18);
outtextxy(W-DW-DC-200+15,H-DH-4*36+12,"1.角度θ_径向速度");//写控件字符串
//------------------------------------------------------------
setcolor(cc2);//说明曲线颜色
line(W-DW-DC-200,H-DH-3*36+18,W-DW-DC-260,H-DH-3*36+18);
outtextxy(W-DW-DC-200+15,H-DH-3*36+12,"2.角度θ_合成速度");//写控件字符串
//------------------------------------------------------------
setcolor(cc3);//说明曲线颜色
line(W-DW-DC-200,H-DH-2*36+18,W-DW-DC-260,H-DH-2*36+18);
outtextxy(W-DW-DC-200+15,H-DH-2*36+12,"3.角度θ_切向速度");//写控件字符串
//------------------------------------------------------------
//7.获取角度变化时的变化曲线------------------------------------------------
double x_scale=(W-2*DW-DC)*0.1/(1.0*(90.0-d6));//每个数学单位x对应的屏幕单位
double y_scale=(H-DH-DD)*1.0/(1.0*d8);//每个数学单位y对应的屏幕单位
double y_scale1=(H-DH-DD)*1.0/(2.0*d10);//每个数学单位y对应的屏幕单位
double n1,n2,n3;//
DPOINT *p1;//定义指向点表的指针
DPOINT *p2;//定义指向点表的指针
DPOINT *p3;//定义指向点表的指针
DPOINT *p4;//定义指向点表的指针
p1=new DPOINT[1000];//定义N1点表
p2=new DPOINT[1000];//定义N2点表
p3=new DPOINT[1000];//定义N3点表
p4=new DPOINT[1000];//定义N3点表
for(int j=0;j<=(90.0-d6)*10.0;j++)//角度变化
{
double xr=(d6+j*0.1)*PI/180.0;//角度
func_xi_v(k2,tt,xr,&n1);//13.径向速度v1(m/s)
n2=n1/(1.0*cos(xr));//15.合成速度v(m/s)
n3=n2*sin(xr);//14.切向速度v2(m/s)
p1[j].x=DW+j*x_scale;
p1[j].y=H-DH-n1*y_scale;
p2[j].x=DW+j*x_scale;
p2[j].y=H-DH-n2*y_scale1;
p3[j].x=DW+j*x_scale;
p3[j].y=H-DH-n3*y_scale1;
p4[j].x=DW+j*x_scale;
p4[j].y=H-DH-n1*y_scale1;
}//结束for
//8.绘制时间角度变化时的变化曲线---------------------------------------------------
setcolor(cc1);//13.径向速度v1(m/s)
for(j=0;j<=(90.0-d6)*10.0-1;j++)//
{
line(p1[j].x,p1[j].y,p1[j+1].x,p1[j+1].y);//大比例
line(p4[j].x,p4[j].y,p4[j+1].x,p4[j+1].y);//小比例
}//结束for
setcolor(cc2);//15.合成速度v(m/s)
for(j=0;j<=(90.0-d6)*10.0-1;j++)//
{
line(p2[j].x,p2[j].y,p2[j+1].x,p2[j+1].y);
}//结束for
setcolor(cc3);//14.切向速度v2(m/s)
for(j=0;j<=(90.0-d6)*10.0-1;j++)//
{
line(p3[j].x,p3[j].y,p3[j+1].x,p3[j+1].y);
}//结束for
}//结束子函数
//--------------------------------------------------------------------------------------------------
void func_xi_v(double k2,double tt,double xi,double *v)//根据角度求速度
{
*v=k2*tt*(1/(4.0*tt*tt)-pow((cos(xi)-(0.5/tt)),2.0));//
}//结束子函数
//*/
//--------------------------------------------------------------------------------------------------------------------
数学模型小作业(风帆动力模型)
于 2023-12-10 11:22:00 首次发布