FPLOT.EXE更新至1.7版,新架构更稳定。
下载链接: https://pan.baidu.com/s/1Mai3MaUQrVLD5Nh_JM2KvQ?pwd=8kvy

摘要:
=============================================================================
控制台数学函数绘图工具,支持几乎所有的数学函数表达式绘制,支持标准直角坐标、
极坐标、参数方程、参数极方程的绘制。
采用剪枝算法,具备极高绘制精度、速度,同时自动过滤间断点、无穷点。自动上色、
自动编号、自动筛选有效定义域。这是一个完全媲美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++编译器) | | | | | | | | | | | | | #include <math.h> | | #include <time.h> | | #include <stdio.h> | | #include <windows.h> | | #include <gdiplus\gdiplus.h> | | | | | | 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 7 | | static 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); | | } | | | | | | HWND hCMD=GetConsoleWindow(); | | HDC hDC =GetDC(hCMD); | | | | | | 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: | | | | tp1=fabsf(atof(argv[i+1])), tp2=fabsf(atof(argv[i+2])); | | | | 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: | | | | 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: | | | | if(!dMARK){ | | | | drawAXY(graph); | | dMARK=TRUE; | | } | | hCOLOR=(srCOLOR++)%15; | | drawFUN(graph, (SN==2)?TRUE:FALSE, argv[i+1], argv[i+2]); | | break; | | | | default: | | | | fputs(HELP_INFORMATION, stderr); | | exit(1); | | } | | i+=SENSITIVE_ARGVS[SN]; | | | | | | }else{ | | fprintf(stderr, "An error occurred near '%s'\n", argv[i]); | | exit(1); | | } | | } | | | | | | | | | | | | DeleteObject(graph); | | DeleteObject(tBRUSH); | | DeleteObject(tFONT); | | DeleteObject(fontFAMILY); | | | | | | ReleaseDC(NULL, hDC2); | | DeleteDC(hDC2); | | DeleteObject(hBitmap2); | | | | | | ReleaseDC(hCMD, hDC); | | DeleteDC(hDC); | | } | | | | | | int main(int argc, char** argv) | | { | | | | ULONG_PTR gdipludToken; | | GdiplusStartupInput gdiplusInput; | | GdiplusStartup(&gdipludToken,&gdiplusInput,NULL); | | | | | | OptRE(argc, argv); | | | | | | GdiplusShutdown(gdipludToken); | | return 0; | | }COPY |
|