|
FPLOT.EXE函数绘图工具,一直开源,从不保留。
下载:
摘要:
=============================================================================
数学函数绘图工具,支持几乎所有的数学函数表达式绘制,支持标准直角坐标、
极坐标、参数方程、参数极方程的绘制。
采用剪枝算法,具备极高绘制精度、速度,同时自动过滤间断点、无穷点。自动上色、
自动编号、自动筛选有效定义域。这是一个完全媲美GNU PLOT的工具,纯命令行操作,
更少的开关,简约而不简单。
=============================================================================
用法:
-----------------------------------------------------------------------------
fplot [options] {arguments}...
-----------------------------------------------------------------------------
/zoom [x-zoom] [y-zoom] //设置水平缩放、垂直缩放率
/move [x-move] [y-move] //设置水平偏移、垂直偏移值
/plo(t|p) [indvar] [expression] //待绘制自变量、因变量字串
-----------------------------------------------------------------------------
注意: 绘直角坐标用/plot,绘极坐标用/plop。
示例:
-----------------------------------------------------------------------------
fplot /zoom 30 30 /plot x sin(x) //放大30倍,自变量为x,绘制sin(x)
fplot /zoom 300 300 /plop x sin(x) //放大300倍,按照极坐标方式绘制
fplot /zoom 0 0 //清除图像
fplot /zoom 0 1 //隐藏光标
fplot /zoom 1 0 //显示光标
-----------------------------------------------------------------------------
备注:
-----------------------------------------------------------------------------
常数类
pi 3.1415926535897932
e 2.7182818284590452
通用类
rand 随机数
round 四舍五入
int 取整
ceil 向上舍入
floor 向下舍入
abs 绝对值
sqrt 开方
lg 常用对数,以10为底
ln 自然对数
exp e的次幂
gamma 伽玛函数
torad 度转弧度
+ 加
- 减
* 乘
/ 除
% 取余数
^ 次方
! 阶乘
三角函数类
sin、cos、tan
arcsin、arccos、arctan
双曲函数类
sinh、cosh、tanh
arcsinh、arccosh、arctanh
-----------------------------------------------------------------------------
英译:
-----------------------------------------------------------------------------
CONSOLE FUNCTION DRAWING TOOL, COPYRIGHT@2017~2019 BY HAPPY
-----------------------------------------------------------------------------
fplot [options] {arguments}...
-----------------------------------------------------------------------------
/zoom [x-zoom] [y-zoom]
/move [x-move] [y-move]
/plo(t|p) [indvar] [expression]
-----------------------------------------------------------------------------
2017-02-11 VERSION 1.7"
原创代码:(仅支持g++编译器)- /* CONSOLE FUNCTION DRAWING TOOL, COPYRIGHT@2017~2019 BY HAPPY, VERSION 1.0 FPLOT.EXE LINK GDIPLUS.LIB GDI32.LIB*/#include <math.h>#include <time.h>#include <stdio.h>#include <windows.h>#include <gdiplus\gdiplus.h>//使用GDI+using namespace Gdiplus;//申明函数extern "C" HWND WINAPI GetConsoleWindow();//定义帮助说明#define HELP_INFORMATION "\-----------------------------------------------------------------\n\CONSOLE FUNCTION DRAWING TOOL, COPYRIGHT@2017~2019 BY HAPPY\n\-----------------------------------------------------------------\n\fplot [options] {arguments}...\n\-----------------------------------------------------------------\n\ /zoom [x-zoom] [y-zoom]\n\ /move [x-move] [y-move]\n\ /plo(t|p) [indvar] [expression]\n\-----------------------------------------------------------------\n\2017-02-12 VERSION 1.7"/***************定义全局变量*************///定义开关词目#define SENSITIVE_NUM 7static const char* SENSITIVE_WORDS[]={"/ZOOM", "/MOVE", "/PLOT", "/PLOP", "/HELP", "/H", "/?"};static const char SENSITIVE_ARGVS[]={ 2, 2, 2, 2, 0, 0, 0};//数学函数词目static const char* KEY_WORDS[]={"E", "PI", "SQRT", "LG", "LN", "SIN", "COS", "TAN", "ARCSIN", "ARCCOS", "ARCTAN", "TORAD", "ABS", "ROUND", "FLOOR", "CEIL", "EXP", "SINH", "COSH", "TANH", "ARCSINH", "ARCCOSH", "ARCTANH", "INT", "GAMMA", "X", NULL};//堆栈尺寸#define STACK_SIZE 1024//运算符栈static char STACK1[STACK_SIZE]={0};//逆波兰栈 static char STACK2[STACK_SIZE]={0};//浮点数栈static float STACK3[STACK_SIZE]={0};//定义绘线属性static float xZOOM=50, yZOOM=50, xMOVE=0, yMOVE=0, hCOLOR=0, hPREC=1000, hMARK=12, xOFFSET=0, yOFFSET=0;//主窗区域RECT winRECT={0};LPRECT lrRECT;//字符串存储容器static WCHAR Tainer[1024]={0}; static CHAR FTainer[32] ={0}; //定义颜色结构体typedef struct{ BYTE R; BYTE G; BYTE B; COLORREF VALUE;}STRGB;//十六色系数组static const STRGB PARGB[15]={ {255, 0, 0,RGB(255, 0, 0)}, //红色 { 33,198,239,RGB( 33,198,239)}, //未蓝 {255,255, 0,RGB(255,255, 0)}, //黄色 {238,130,238,RGB(238,130,238)}, //紫兰 {165, 42, 42,RGB(165, 42, 42)}, //棕色 {144,238,144,RGB(144,238,144)}, //浅绿 { 0, 0,255,RGB( 0, 0,255)}, //蓝色 {255, 0,255,RGB(255, 0,255)}, //洋紫 {169,169,169,RGB(169,169,169)}, //深灰 {173,216,230,RGB(173,216,230)}, //淡蓝 {248, 29, 56,RGB(248, 29, 56)}, //亮红 { 0,255, 0,RGB( 0,255, 0)}, //绿色 {224,255,255,RGB(224,255,255)}, //淡青 { 0,255,255,RGB( 0,255,255)}, //青色 {255,255,255,RGB(255,255,255)} //白色};//创建绘图字体 FontFamily* fontFAMILY;//设置字体属性 Font* tFONT, *nFONT;//创建字体画刷 SolidBrush* tBRUSH; /***************逆波兰核心***************/ float RevPolishCore(const char* expression, float varV){ char *op=(char*)expression, *S1=STACK1, *S2=STACK2, **key, *cp, *kp; float *S3=STACK3, di, ni; int brackets=0; STACK3[0]=0; //生成逆波兰 while(*op!='\0'){ switch(*op){ case ' ' : case '\t': case '\r': case '\n': //过滤空字符 op++; continue; case '(': brackets++; *(++S1)=*op; if(*(op+1)=='-' || *(op+1)=='+'){ *(S2++)='0', *(S2++)=' '; } break; case ')': //验证括号是否闭合 if(brackets ==0){ fputs("The brackets or ')' are not need", stderr); exit(1); } brackets--; while(*S1!='(') { *(S2++)=*(S1--); } //舍弃'(' S1--; break; case '+': case '-': while(S1!=STACK1 && *S1!='(') { *(S2++)=*(S1--); } *(++S1)=*op; break; case '^': //指数符 while( ('A'<=(*S1) && (*S1)<='Z') ) { *(S2++)=*(S1--); } *(++S1)=*op; break; case '!': //阶乘符 *(S2++)=*op; break; case '%': case '*': case '/': while(('A'<=(*S1) && (*S1)<='Z') ||*S1=='%' ||*S1=='*' ||*S1=='/' ||*S1=='^'){ *(S2++)=*(S1--); } *(++S1)=*op; break; default : if( ('a'<=*op && *op<='z') || ('A'<=*op && *op<='Z') ){ //识别数学函数关键词 key=(char**)KEY_WORDS; while(*key !=NULL){ cp=op, kp=*key; //比对关键词字母 while((*cp==*kp||*cp==*kp+32) && *kp!='\0'){ cp++, kp++; } //验证关键词结尾 if( ((*cp<'A')||('Z'<*cp && *cp<'a')||(*cp>'z')) && (*kp=='\0') ){ op=cp; break; } key++; } //构建伪双目 *(S2++)='.'; *(S2++)=' '; //伪双目入栈 while( ('A'<=(*S1) && (*S1)<='Z') ){ *(S2++)=*(S1--); } if(*key !=NULL){ *(++S1)=key-(char**)KEY_WORDS+65; }else{ while( ('a'<=*op && *op<='z') || ('A'<=*op && *op<='Z') ){op++;} *(++S1)='Z'; } continue; }else if(('0'<=*op && *op<='9') || (*op=='.')){ //浮点数入栈 while(('0'<=*op && *op<='9') || (*op=='.')){ *(S2++)=*(op++); } if( ('a'<=*op && *op<='z') || ('A'<=*op && *op<='Z') ){ //缺少必要的运算符 fputs("Missing required operator\n", stderr); exit(1); } op--; *(S2++)=' '; }else{ //无法识别的运算符 fputs("Unrecognized operator\n", stderr); exit(1); } break; } op++; } //验证括号是否闭合 if(brackets !=0){ fputs("The brackets '(' are not closed", stderr); exit(1); } //收尾逆波兰 while(S1 !=STACK1){*(S2++)=*(S1--);} *S2=' '; //计算逆波兰 op=STACK2; while(*op!=' '){ switch(*op){ case 'A': *S3=2.7182818284590452; break; case 'B': *S3=3.1415926535897932; break; case 'C': *(S3-1)=sqrtf(*S3); S3--; break; case 'D': *(S3-1)=log10f(*S3); S3--; break; case 'E': *(S3-1)=logf(*S3); S3--; break; case 'F': *(S3-1)=sinf(*S3); S3--; break; case 'G': *(S3-1)=cosf(*S3); S3--; break; case 'H': *(S3-1)=tanf(*S3); S3--; break; case 'I': *(S3-1)=asinf(*S3); S3--; break; case 'J': *(S3-1)=acosf(*S3); S3--; break; case 'K': *(S3-1)=atanf(*S3); S3--; break; case 'L': *(S3-1)=(*S3)*3.1415926535897932/180.0; S3--; break; case 'M': *(S3-1)=fabsf(*S3); S3--; break; case 'N': *(S3-1)=roundf(*S3); S3--; break; case 'O': *(S3-1)=floorf(*S3); S3--; break; case 'P': *(S3-1)=ceilf(*S3); S3--; break; case 'Q': *(S3-1)=expf(*S3); S3--; break; case 'R': *(S3-1)=sinhf(*S3); S3--; break; case 'S': *(S3-1)=coshf(*S3); S3--; break; case 'T': *(S3-1)=tanhf(*S3); S3--; break; case 'U': *(S3-1)=asinhf(*S3); S3--; break; case 'V': *(S3-1)=acoshf(*S3); S3--; break; case 'W': *(S3-1)=atanhf(*S3); S3--; break; case 'X': *(S3-1)=(int)(*S3); S3--; break; case 'Y': *(S3-1)=tgammaf(*S3); S3--; break; case 'Z': *S3=varV; break; case '+': *(S3-1)+=*S3; S3--; break; case '-': *(S3-1)-=*S3; S3--; break; case '*': *(S3-1)*=*S3; S3--; break; case '%': case '/': if(*op=='%'){ //取余数 *(S3-1)=(int)*(S3-1) % (int)*S3; }else{ *(S3-1)/=*S3; } S3--; break; case '^': *(S3-1)=powf(*(S3-1), *S3); S3--; break; case '!': *S3=tgammaf(*S3+1); break; default : //字符串转浮点 di=0, ni=1; while('0'<=*op && *op<='9'){ di=10*di+(*op)-'0'; op++; } if(*op=='.'){ op++; while('0'<=*op && *op<='9'){ di=10*di+(*op)-'0'; op++, ni*=10; } } *(++S3)=di/ni; break; } op++; } //返回计算结果 return *S3;}/***************功能函数群***************///光标函数 BOOL DispyCursor(int size,bool mode){ CONSOLE_CURSOR_INFO cinfo ={(DWORD)size, mode}; return SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cinfo); }//转码函数WCHAR* L(const CHAR* str){ if(!str){return NULL;} int wLen=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, NULL, 0); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, Tainer, wLen); Tainer[wLen]='\0'; return Tainer;}//辨关键词int itifyWORDS(const char* strARGV){ int i, SN; for(SN=0; SN<SENSITIVE_NUM; SN++){ char *op=(char*)strARGV, *kp=(char*)SENSITIVE_WORDS[SN]; while(*kp!='\0'){ if( (('a'<= *op && *op<='z')?*op-32:*op) != (('a'<= *kp && *kp<='z')?*kp-32:*kp) ){break;} op++;kp++; } if( (*kp=='\0') && (*op==' '||*op=='\t'||*op=='\r'||*op=='\n'||*op=='\0') ){return SN;} } return -1;}//显示数字void drawNUMS(Graphics *graph, float fnum, float px, float py){ sprintf(FTainer, "%.5g", fnum); graph->DrawString(L(FTainer), -1, tFONT, PointF(px,py), tBRUSH);}//绘制刻度void drawAXY(Graphics *graph){ //设置坐标字体 Font fontp(fontFAMILY, 12, FontStyleRegular, UnitPixel); tFONT=&fontp; //设置曲线光滑 graph->SetSmoothingMode(SmoothingModeHighQuality); //创建白色画笔 Pen *pen, pez(Color(160, 255, 255, 255), 1), pep(Color(160, 255, 255, 255), 1); //设置虚线画笔 pez.SetDashStyle(DashStyleDash); for(int i=0; i<=lrRECT->right*2; i+=50){ //绘制坐标 if(i==0){ //绘制坐标原点 drawNUMS(graph, 0, xOFFSET, yOFFSET); }else{ //绘制坐标刻度 drawNUMS(graph, i/xZOOM, xOFFSET+i, yOFFSET); drawNUMS(graph, 0-i/xZOOM, xOFFSET-i, yOFFSET); drawNUMS(graph, 0-i/yZOOM, xOFFSET, yOFFSET+i); drawNUMS(graph, i/yZOOM, xOFFSET, yOFFSET-i); } //绘制网格 if(i==0){ pen=&pep; }else{ pen=&pez; } graph->DrawLine(pen, PointF(0, yOFFSET+i), PointF(lrRECT->right, yOFFSET+i)); graph->DrawLine(pen, PointF(0, yOFFSET-i), PointF(lrRECT->right, yOFFSET-i)); graph->DrawLine(pen, PointF(xOFFSET+i, 0), PointF(xOFFSET+i,lrRECT->bottom)); graph->DrawLine(pen, PointF(xOFFSET-i, 0), PointF(xOFFSET-i,lrRECT->bottom)); } //清理对象 DeleteObject(pen); DeleteObject(&pez); DeleteObject(&pep); DeleteObject(&fontp);}//绘制曲线void drawFUN(Graphics *graph, BOOL penMODE, const char* varression, const char* expression){ //设置绘图曲线光滑 graph->SetSmoothingMode(SmoothingModeHighQuality); //创建彩色画笔 STRGB* penRGB=(STRGB*)&PARGB[(int)hCOLOR]; Pen pep(Color(255,penRGB->R,penRGB->G,penRGB->B), 2), *pen=&pep; //设置注释字体 Font fontp(fontFAMILY, 13, FontStyleBold, UnitPixel); tFONT=&fontp; //绘制函数注释 graph->DrawLine(pen, PointF(2, hMARK+6), PointF(20, hMARK+6)); graph->DrawString(L(expression), -1, tFONT, PointF(20,hMARK), tBRUSH); hMARK+=16; //绘制函数曲线 float t, x1, y1, x2, y2, t_start=(-lrRECT->right/2.0-xMOVE)/xZOOM, t_end=(lrRECT->right/2.0-xMOVE)/xZOOM, add=lrRECT->right/xZOOM/hPREC, y_start=2*(-lrRECT->bottom/2.0-yMOVE)/yZOOM, y_end=2*(lrRECT->bottom/2.0-yMOVE)/yZOOM; if(penMODE){ //直角坐标 x1=RevPolishCore(varression, t_start), y1=RevPolishCore(expression, t_start); for(t=t_start; t<=t_end; t+=add){ x2=RevPolishCore(varression, t+add), y2=RevPolishCore(expression, t+add); if((t!=t_start) && (y_start<y1 && y1<y_end) && (y_start<y2 && y2<y_end)){ graph->DrawLine(pen, PointF(xZOOM*x1+xOFFSET, -yZOOM*y1+yOFFSET), PointF(xZOOM*x2+xOFFSET, -yZOOM*y2+yOFFSET)); } x1=x2, y1=y2; } }else{ //极轴坐标 x1=RevPolishCore(varression, t_start), y1=RevPolishCore(expression, t_start); for(t=t_start; t<=t_end*5; t+=add){ x2=RevPolishCore(varression, t+add), y2=RevPolishCore(expression, t+add); if((t!=t_start) && (y_start<y1 && y1<y_end) && (y_start<y2 && y2<y_end)){ graph->DrawLine(pen, PointF(xZOOM*y1*cos(x1)+xOFFSET, -yZOOM*y1*sin(x1)+yOFFSET), PointF(xZOOM*y2*cos(x2)+xOFFSET, -yZOOM*y2*sin(x2)+yOFFSET)); } x1=x2, y1=y2; } } //清理对象 DeleteObject(pen); DeleteObject(&pep); DeleteObject(&fontp);}//开关解析void OptRE(int argc, char** argv){ //计算有效参数数目 int oargc=argc-1, anum; if(oargc==0){ //无参数,则抛出使用说明 fputs(HELP_INFORMATION, stderr); exit(1); } //获取CMD窗口句柄 HWND hCMD=GetConsoleWindow(); HDC hDC =GetDC(hCMD); //获取CMD窗口大小 lrRECT=&winRECT; GetClientRect(hCMD, lrRECT); //获取像素坐标基值 xOFFSET=lrRECT->right/2, yOFFSET=lrRECT->bottom/2; //创建加速内存画布 HWND hWND2=NULL; HDC hDC2=CreateCompatibleDC(hDC); HBITMAP hBitmap2=CreateCompatibleBitmap(hDC, lrRECT->right, lrRECT->bottom); SelectObject(hDC2, hBitmap2); //创建绘图工具 Graphics graphicsp(hDC), *graph=&graphicsp; //创建绘图字体 FontFamily fontf(L"SimSun"); fontFAMILY=&fontf; //创建字体画刷 SolidBrush brushp(Color(255, 255, 255, 255)); tBRUSH=&brushp; //初始化线条颜色 int srCOLOR=0; //参数接收针 char** oargv=argv; //参数累加器 int i=0; //坐标绘制态 BOOL dMARK=FALSE; //临时变量 float tp1, tp2; //开启主循环 while((++i)<=oargc){ int SN=itifyWORDS(argv[i]); if(SN!=-1){ if(i+SENSITIVE_ARGVS[SN]>oargc){ //缺少必要参数 fprintf(stderr, "The option '%s' needs %d parameters\n", argv[i], SENSITIVE_ARGVS[SN]); exit(1); } for(anum=1; anum<=SENSITIVE_ARGVS[SN]; anum++){ if(oargv[i+anum][0]==SENSITIVE_WORDS[0][0]){ //缺少必要参数 fprintf(stderr, "Only %d parameters, the option '%s' needs %d parameters\n", anum-1, argv[i], SENSITIVE_ARGVS[SN]); exit(1); } } //执行开关命令 switch(SN) { case 0: //ZOOM tp1=fabsf(atof(argv[i+1])), tp2=fabsf(atof(argv[i+2])); //解析ZOOM开关的隐藏功能 if(tp1*tp2==0){ if(tp2!=0){ DispyCursor((DWORD)25, FALSE); }else if(tp1!=0){ DispyCursor((DWORD)25, TRUE ); }else{ InvalidateRect(hCMD, NULL, FALSE); dMARK=FALSE; } break; } InvalidateRect(hCMD, NULL, FALSE); dMARK=FALSE, srCOLOR=0, hMARK=12; xZOOM=tp1, yZOOM=tp2; break; case 1: //MOVE if(dMARK){ InvalidateRect(hCMD, NULL, FALSE); dMARK=FALSE, srCOLOR=0, hMARK=12; } xMOVE=atof(argv[i+1]), yMOVE=atof(argv[i+2]); xOFFSET+=xMOVE, yOFFSET-=yMOVE; break; case 2: case 3: //PLOP||PLOT if(!dMARK){ //调用坐标绘制函数 drawAXY(graph); dMARK=TRUE; } hCOLOR=(srCOLOR++)%15; drawFUN(graph, (SN==2)?TRUE:FALSE, argv[i+1], argv[i+2]); break; default: //HELP fputs(HELP_INFORMATION, stderr); exit(1); } i+=SENSITIVE_ARGVS[SN]; //无法识别的参数 }else{ fprintf(stderr, "An error occurred near '%s'\n", argv[i]); exit(1); } } //从内存画布复制到CMD画布 //BitBlt(hDC,0,0,lrRECT->right,lrRECT->bottom, hDC2,0,0,SRCCOPY); //清理绘图工具 DeleteObject(graph); DeleteObject(tBRUSH); DeleteObject(tFONT); DeleteObject(fontFAMILY); //释放内存画布 ReleaseDC(NULL, hDC2); DeleteDC(hDC2); DeleteObject(hBitmap2); //释放CMD 画布 ReleaseDC(hCMD, hDC); DeleteDC(hDC);}/*************MAIN主函数入口*************/int main(int argc, char** argv){ //初始化GdiPlus ULONG_PTR gdipludToken; GdiplusStartupInput gdiplusInput; GdiplusStartup(&gdipludToken,&gdiplusInput,NULL); //解析开关 OptRE(argc, argv); //关闭Gdiplus GdiplusShutdown(gdipludToken); return 0;}
复制代码 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|