找回密码
 欢迎注册
查看: 10462|回复: 3

[原创] 原创函数绘图工具fplot.exe

[复制链接]
发表于 2017-2-12 22:47:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
本帖最后由 happysxyf 于 2017-2-12 22:53 编辑
FPLOT.EXE函数绘图工具,一直开源,从不保留。
下载: fplot源码.zip (23.95 KB, 下载次数: 18)
QQ图片20170212224845.png
摘要:
=============================================================================
数学函数绘图工具,支持几乎所有的数学函数表达式绘制,支持标准直角坐标、
极坐标、参数方程、参数极方程的绘制。

采用剪枝算法,具备极高绘制精度、速度,同时自动过滤间断点、无穷点。自动上色、
自动编号、自动筛选有效定义域。这是一个完全媲美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++编译器)

  1. /*
  2.         CONSOLE FUNCTION DRAWING TOOL, COPYRIGHT@2017~2019 BY HAPPY, VERSION 1.0
  3.         FPLOT.EXE
  4.         LINK GDIPLUS.LIB GDI32.LIB
  5. */

  6. #include <math.h>
  7. #include <time.h>
  8. #include <stdio.h>
  9. #include <windows.h>
  10. #include <gdiplus\gdiplus.h>

  11. //使用GDI+
  12. using namespace Gdiplus;

  13. //申明函数
  14. extern "C" HWND WINAPI GetConsoleWindow();

  15. //定义帮助说明
  16. #define HELP_INFORMATION "\
  17. -----------------------------------------------------------------\n\
  18. CONSOLE FUNCTION DRAWING TOOL, COPYRIGHT@2017~2019 BY HAPPY\n\
  19. -----------------------------------------------------------------\n\
  20. fplot  [options] {arguments}...\n\
  21. -----------------------------------------------------------------\n\
  22.        /zoom     [x-zoom] [y-zoom]\n\
  23.        /move     [x-move] [y-move]\n\
  24.        /plo(t|p) [indvar] [expression]\n\
  25. -----------------------------------------------------------------\n\
  26. 2017-02-12 VERSION 1.7"

  27. /***************定义全局变量*************/
  28. //定义开关词目
  29. #define            SENSITIVE_NUM   7
  30. static const char* SENSITIVE_WORDS[]={"/ZOOM", "/MOVE", "/PLOT", "/PLOP", "/HELP", "/H", "/?"};
  31. static const char  SENSITIVE_ARGVS[]={      2,       2,       2,       2,       0,    0,    0};

  32. //数学函数词目
  33. 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};
  34. //堆栈尺寸
  35. #define  STACK_SIZE      1024
  36. //运算符栈
  37. static char   STACK1[STACK_SIZE]={0};
  38. //逆波兰栈
  39. static char   STACK2[STACK_SIZE]={0};
  40. //浮点数栈
  41. static float  STACK3[STACK_SIZE]={0};

  42. //定义绘线属性
  43. static float  xZOOM=50, yZOOM=50, xMOVE=0, yMOVE=0, hCOLOR=0, hPREC=1000, hMARK=12, xOFFSET=0, yOFFSET=0;

  44. //主窗区域
  45. RECT          winRECT={0};
  46. LPRECT        lrRECT;

  47. //字符串存储容器
  48. static WCHAR  Tainer[1024]={0};  
  49. static CHAR   FTainer[32] ={0};  

  50. //定义颜色结构体
  51. typedef struct{
  52.         BYTE R;
  53.         BYTE G;
  54.         BYTE B;
  55.         COLORREF VALUE;
  56. }STRGB;
  57. //十六色系数组
  58. static const STRGB PARGB[15]={
  59.         {255,  0,  0,RGB(255,  0,  0)}, //红色
  60.         { 33,198,239,RGB( 33,198,239)}, //未蓝
  61.         {255,255,  0,RGB(255,255,  0)}, //黄色
  62.         {238,130,238,RGB(238,130,238)}, //紫兰
  63.         {165, 42, 42,RGB(165, 42, 42)}, //棕色
  64.         {144,238,144,RGB(144,238,144)}, //浅绿
  65.         {  0,  0,255,RGB(  0,  0,255)}, //蓝色
  66.         {255,  0,255,RGB(255,  0,255)}, //洋紫
  67.         {169,169,169,RGB(169,169,169)}, //深灰
  68.         {173,216,230,RGB(173,216,230)}, //淡蓝
  69.         {248, 29, 56,RGB(248, 29, 56)}, //亮红
  70.         {  0,255,  0,RGB(  0,255,  0)}, //绿色
  71.         {224,255,255,RGB(224,255,255)}, //淡青
  72.         {  0,255,255,RGB(  0,255,255)}, //青色
  73.         {255,255,255,RGB(255,255,255)}  //白色
  74. };

  75. //创建绘图字体
  76. FontFamily* fontFAMILY;
  77. //设置字体属性
  78. Font* tFONT, *nFONT;
  79. //创建字体画刷
  80. SolidBrush* tBRUSH;
  81.        
  82. /***************逆波兰核心***************/
  83. float RevPolishCore(const char* expression, float varV)
  84. {
  85.         char  *op=(char*)expression, *S1=STACK1, *S2=STACK2, **key, *cp, *kp;
  86.         float *S3=STACK3, di, ni;
  87.         int    brackets=0;
  88.         STACK3[0]=0;
  89.        
  90.         //生成逆波兰       
  91.         while(*op!='\0'){               
  92.                 switch(*op){
  93.                 case ' ' :
  94.                 case '\t':
  95.                 case '\r':
  96.                 case '\n':
  97.                         //过滤空字符
  98.                         op++;
  99.                         continue;
  100.                
  101.                 case '(':
  102.                         brackets++;
  103.                         *(++S1)=*op;
  104.                         if(*(op+1)=='-' || *(op+1)=='+'){
  105.                                 *(S2++)='0', *(S2++)=' ';
  106.                         }
  107.                         break;

  108.                 case ')':
  109.                         //验证括号是否闭合
  110.                         if(brackets ==0){
  111.                                 fputs("The brackets or ')' are not need", stderr);
  112.                                 exit(1);
  113.                         }
  114.                         brackets--;
  115.                         while(*S1!='(')
  116.                         {
  117.                                 *(S2++)=*(S1--);
  118.                         }               
  119.                         //舍弃'('
  120.                         S1--;               
  121.                         break;

  122.                 case '+':
  123.                 case '-':
  124.                         while(S1!=STACK1 && *S1!='(')
  125.                         {
  126.                                 *(S2++)=*(S1--);
  127.                         }
  128.                         *(++S1)=*op;
  129.                         break;

  130.                 case '^':
  131.                         //指数符
  132.                         while( ('A'<=(*S1) && (*S1)<='Z') )
  133.                         {
  134.                                 *(S2++)=*(S1--);
  135.                         }
  136.                         *(++S1)=*op;
  137.                         break;

  138.                 case '!':
  139.                         //阶乘符
  140.                         *(S2++)=*op;
  141.                         break;

  142.                 case '%':
  143.                 case '*':
  144.                 case '/':
  145.                         while(('A'<=(*S1) && (*S1)<='Z') ||*S1=='%' ||*S1=='*' ||*S1=='/' ||*S1=='^'){
  146.                                 *(S2++)=*(S1--);
  147.                         }
  148.                         *(++S1)=*op;
  149.                         break;

  150.                 default :
  151.                         if(
  152.                                 ('a'<=*op && *op<='z') ||
  153.                                 ('A'<=*op && *op<='Z')
  154.                         ){
  155.                                 //识别数学函数关键词
  156.                                 key=(char**)KEY_WORDS;
  157.                                 while(*key !=NULL){       
  158.                                         cp=op, kp=*key;
  159.                                         //比对关键词字母
  160.                                         while((*cp==*kp||*cp==*kp+32) && *kp!='\0'){
  161.                                                 cp++, kp++;
  162.                                         }
  163.                                         //验证关键词结尾
  164.                                          if( ((*cp<'A')||('Z'<*cp && *cp<'a')||(*cp>'z')) && (*kp=='\0') ){
  165.                                                  op=cp;
  166.                                                 break;
  167.                                         }
  168.                                         key++;
  169.                                 }
  170.                                 //构建伪双目                        
  171.                                 *(S2++)='.';
  172.                                 *(S2++)=' ';
  173.                                 //伪双目入栈
  174.                                 while( ('A'<=(*S1) && (*S1)<='Z') ){
  175.                                         *(S2++)=*(S1--);
  176.                                 }
  177.                                 if(*key !=NULL){
  178.                                         *(++S1)=key-(char**)KEY_WORDS+65;
  179.                                 }else{
  180.                                         while(
  181.                                                 ('a'<=*op && *op<='z') ||
  182.                                                 ('A'<=*op && *op<='Z')
  183.                                         ){op++;}
  184.                                         *(++S1)='Z';
  185.                                 }
  186.                                 continue;

  187.                         }else if(('0'<=*op && *op<='9') || (*op=='.')){
  188.                                 //浮点数入栈
  189.                                 while(('0'<=*op && *op<='9') || (*op=='.')){
  190.                                         *(S2++)=*(op++);
  191.                                 }
  192.                                 if(
  193.                                         ('a'<=*op && *op<='z') ||
  194.                                         ('A'<=*op && *op<='Z')
  195.                                 ){
  196.                                         //缺少必要的运算符
  197.                                         fputs("Missing required operator\n", stderr);
  198.                                         exit(1);       
  199.                                 }
  200.                                 op--;
  201.                                 *(S2++)=' ';

  202.                         }else{
  203.                                 //无法识别的运算符
  204.                                 fputs("Unrecognized operator\n", stderr);
  205.                                 exit(1);
  206.                         }
  207.                         break;
  208.                 }
  209.                 op++;
  210.         }

  211.         //验证括号是否闭合
  212.         if(brackets !=0){
  213.                 fputs("The brackets '(' are not closed", stderr);
  214.                 exit(1);
  215.         }

  216.         //收尾逆波兰
  217.         while(S1 !=STACK1){*(S2++)=*(S1--);}
  218.         *S2=' ';

  219.         //计算逆波兰
  220.         op=STACK2;
  221.         while(*op!=' '){
  222.                 switch(*op){
  223.                 case 'A':
  224.                         *S3=2.7182818284590452;
  225.                         break;
  226.                 case 'B':
  227.                         *S3=3.1415926535897932;
  228.                         break;
  229.                 case 'C':
  230.                         *(S3-1)=sqrtf(*S3);
  231.                         S3--;
  232.                         break;
  233.                 case 'D':
  234.                         *(S3-1)=log10f(*S3);
  235.                         S3--;
  236.                         break;
  237.                 case 'E':
  238.                         *(S3-1)=logf(*S3);
  239.                         S3--;
  240.                         break;
  241.                 case 'F':
  242.                         *(S3-1)=sinf(*S3);
  243.                         S3--;
  244.                         break;
  245.                 case 'G':
  246.                         *(S3-1)=cosf(*S3);
  247.                         S3--;
  248.                         break;
  249.                 case 'H':
  250.                         *(S3-1)=tanf(*S3);
  251.                         S3--;
  252.                         break;
  253.                 case 'I':
  254.                         *(S3-1)=asinf(*S3);
  255.                         S3--;
  256.                         break;
  257.                 case 'J':
  258.                         *(S3-1)=acosf(*S3);
  259.                         S3--;
  260.                         break;
  261.                 case 'K':
  262.                         *(S3-1)=atanf(*S3);
  263.                         S3--;
  264.                         break;
  265.                 case 'L':
  266.                         *(S3-1)=(*S3)*3.1415926535897932/180.0;
  267.                         S3--;
  268.                         break;
  269.                 case 'M':
  270.                         *(S3-1)=fabsf(*S3);
  271.                         S3--;
  272.                         break;
  273.                 case 'N':
  274.                         *(S3-1)=roundf(*S3);
  275.                         S3--;
  276.                         break;
  277.                 case 'O':
  278.                         *(S3-1)=floorf(*S3);
  279.                         S3--;
  280.                         break;
  281.                 case 'P':
  282.                         *(S3-1)=ceilf(*S3);
  283.                         S3--;
  284.                         break;
  285.                 case 'Q':
  286.                         *(S3-1)=expf(*S3);
  287.                         S3--;
  288.                         break;
  289.                 case 'R':
  290.                         *(S3-1)=sinhf(*S3);
  291.                         S3--;
  292.                         break;
  293.                 case 'S':
  294.                         *(S3-1)=coshf(*S3);
  295.                         S3--;
  296.                         break;
  297.                 case 'T':
  298.                         *(S3-1)=tanhf(*S3);
  299.                         S3--;
  300.                         break;
  301.                 case 'U':
  302.                         *(S3-1)=asinhf(*S3);
  303.                         S3--;
  304.                         break;
  305.                 case 'V':
  306.                         *(S3-1)=acoshf(*S3);
  307.                         S3--;
  308.                         break;
  309.                 case 'W':
  310.                         *(S3-1)=atanhf(*S3);
  311.                         S3--;
  312.                         break;
  313.                 case 'X':
  314.                         *(S3-1)=(int)(*S3);
  315.                         S3--;
  316.                         break;
  317.                 case 'Y':
  318.                         *(S3-1)=tgammaf(*S3);
  319.                         S3--;
  320.                         break;
  321.                 case 'Z':
  322.                         *S3=varV;
  323.                         break;
  324.                 case '+':
  325.                         *(S3-1)+=*S3;
  326.                         S3--;
  327.                         break;
  328.                 case '-':
  329.                         *(S3-1)-=*S3;
  330.                         S3--;
  331.                         break;
  332.                 case '*':
  333.                         *(S3-1)*=*S3;
  334.                         S3--;
  335.                         break;
  336.                 case '%':
  337.                 case '/':
  338.                         if(*op=='%'){
  339.                                 //取余数
  340.                                 *(S3-1)=(int)*(S3-1) % (int)*S3;
  341.                         }else{
  342.                                 *(S3-1)/=*S3;
  343.                         }                       
  344.                         S3--;
  345.                         break;
  346.                 case '^':
  347.                         *(S3-1)=powf(*(S3-1), *S3);
  348.                         S3--;
  349.                         break;
  350.                 case '!':
  351.                         *S3=tgammaf(*S3+1);

  352.                         break;
  353.                 default :
  354.                         //字符串转浮点
  355.                         di=0, ni=1;
  356.                         while('0'<=*op && *op<='9'){
  357.                                 di=10*di+(*op)-'0';
  358.                                 op++;
  359.                         }       
  360.                         if(*op=='.'){
  361.                                 op++;
  362.                                 while('0'<=*op && *op<='9'){
  363.                                         di=10*di+(*op)-'0';
  364.                                         op++, ni*=10;
  365.                                 }       
  366.                         }
  367.                         *(++S3)=di/ni;
  368.                         break;
  369.                 }
  370.                 op++;
  371.         }
  372.         //返回计算结果
  373.         return *S3;
  374. }

  375. /***************功能函数群***************/
  376. //光标函数
  377. BOOL DispyCursor(int size,bool mode)
  378. {
  379.         CONSOLE_CURSOR_INFO cinfo ={(DWORD)size, mode};
  380.         return SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cinfo);         
  381. }
  382. //转码函数
  383. WCHAR* L(const CHAR* str)
  384. {
  385.         if(!str){return NULL;}
  386.         int wLen=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, NULL, 0);
  387.         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, Tainer, wLen);
  388.         Tainer[wLen]='\0';
  389.         return Tainer;
  390. }
  391. //辨关键词
  392. int itifyWORDS(const char* strARGV)
  393. {
  394.         int i, SN;
  395.         for(SN=0; SN<SENSITIVE_NUM; SN++){
  396.                 char *op=(char*)strARGV, *kp=(char*)SENSITIVE_WORDS[SN];
  397.                 while(*kp!='\0'){
  398.                         if( (('a'<= *op && *op<='z')?*op-32:*op) != (('a'<= *kp && *kp<='z')?*kp-32:*kp) ){break;}
  399.                         op++;kp++;
  400.                 }
  401.                  if( (*kp=='\0') && (*op==' '||*op=='\t'||*op=='\r'||*op=='\n'||*op=='\0') ){return SN;}
  402.         }                               
  403.         return -1;
  404. }
  405. //显示数字
  406. void drawNUMS(Graphics *graph, float fnum, float px, float py)
  407. {
  408.         sprintf(FTainer, "%.5g", fnum);
  409.         graph->DrawString(L(FTainer), -1, tFONT, PointF(px,py), tBRUSH);
  410. }
  411. //绘制刻度
  412. void drawAXY(Graphics *graph)
  413. {
  414.         //设置坐标字体
  415.         Font fontp(fontFAMILY, 12, FontStyleRegular, UnitPixel);
  416.         tFONT=&fontp;

  417.         //设置曲线光滑
  418.         graph->SetSmoothingMode(SmoothingModeHighQuality);

  419.         //创建白色画笔
  420.         Pen *pen, pez(Color(160, 255, 255, 255), 1), pep(Color(160, 255, 255, 255), 1);

  421.         //设置虚线画笔
  422.         pez.SetDashStyle(DashStyleDash);

  423.         for(int i=0; i<=lrRECT->right*2; i+=50){
  424.                 //绘制坐标
  425.                 if(i==0){
  426.                         //绘制坐标原点
  427.                         drawNUMS(graph, 0, xOFFSET, yOFFSET);
  428.                 }else{
  429.                         //绘制坐标刻度
  430.                         drawNUMS(graph,   i/xZOOM, xOFFSET+i,   yOFFSET);
  431.                         drawNUMS(graph, 0-i/xZOOM, xOFFSET-i,   yOFFSET);
  432.                         drawNUMS(graph, 0-i/yZOOM,   xOFFSET, yOFFSET+i);
  433.                         drawNUMS(graph,   i/yZOOM,   xOFFSET, yOFFSET-i);
  434.                 }
  435.                 //绘制网格
  436.                 if(i==0){
  437.                         pen=&pep;
  438.                 }else{
  439.                         pen=&pez;
  440.                 }
  441.                 graph->DrawLine(pen, PointF(0,       yOFFSET+i), PointF(lrRECT->right, yOFFSET+i));
  442.                 graph->DrawLine(pen, PointF(0,       yOFFSET-i), PointF(lrRECT->right, yOFFSET-i));
  443.                 graph->DrawLine(pen, PointF(xOFFSET+i,       0), PointF(xOFFSET+i,lrRECT->bottom));
  444.                 graph->DrawLine(pen, PointF(xOFFSET-i,       0), PointF(xOFFSET-i,lrRECT->bottom));
  445.         }

  446.         //清理对象
  447.         DeleteObject(pen);
  448.         DeleteObject(&pez);
  449.         DeleteObject(&pep);
  450.         DeleteObject(&fontp);
  451. }
  452. //绘制曲线
  453. void drawFUN(Graphics *graph, BOOL penMODE, const char* varression, const char* expression)
  454. {
  455.         //设置绘图曲线光滑
  456.         graph->SetSmoothingMode(SmoothingModeHighQuality);

  457.         //创建彩色画笔
  458.         STRGB* penRGB=(STRGB*)&PARGB[(int)hCOLOR];
  459.         Pen pep(Color(255,penRGB->R,penRGB->G,penRGB->B), 2), *pen=&pep;

  460.         //设置注释字体
  461.         Font fontp(fontFAMILY, 13, FontStyleBold, UnitPixel);
  462.         tFONT=&fontp;
  463.         //绘制函数注释
  464.         graph->DrawLine(pen, PointF(2, hMARK+6), PointF(20, hMARK+6));
  465.         graph->DrawString(L(expression), -1, tFONT, PointF(20,hMARK), tBRUSH);
  466.         hMARK+=16;

  467.         //绘制函数曲线
  468.         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;
  469.         if(penMODE){
  470.                 //直角坐标
  471.                 x1=RevPolishCore(varression, t_start), y1=RevPolishCore(expression, t_start);
  472.                 for(t=t_start; t<=t_end; t+=add){
  473.                         x2=RevPolishCore(varression, t+add), y2=RevPolishCore(expression, t+add);
  474.                         if((t!=t_start)  && (y_start<y1 && y1<y_end) && (y_start<y2 && y2<y_end)){
  475.                                 graph->DrawLine(pen, PointF(xZOOM*x1+xOFFSET, -yZOOM*y1+yOFFSET), PointF(xZOOM*x2+xOFFSET, -yZOOM*y2+yOFFSET));
  476.                         }
  477.                         x1=x2, y1=y2;
  478.                 }

  479.         }else{
  480.                 //极轴坐标
  481.                 x1=RevPolishCore(varression, t_start), y1=RevPolishCore(expression, t_start);
  482.                 for(t=t_start; t<=t_end*5; t+=add){
  483.                         x2=RevPolishCore(varression, t+add), y2=RevPolishCore(expression, t+add);
  484.                         if((t!=t_start) && (y_start<y1 && y1<y_end) && (y_start<y2 && y2<y_end)){
  485.                                 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));
  486.                         }
  487.                         x1=x2, y1=y2;
  488.                 }       
  489.         }
  490.        
  491.         //清理对象
  492.         DeleteObject(pen);
  493.         DeleteObject(&pep);
  494.         DeleteObject(&fontp);
  495. }
  496. //开关解析
  497. void OptRE(int argc, char** argv)
  498. {
  499.         //计算有效参数数目
  500.         int oargc=argc-1, anum;
  501.         if(oargc==0){
  502.                 //无参数,则抛出使用说明
  503.                 fputs(HELP_INFORMATION, stderr);
  504.                 exit(1);
  505.         }

  506.         //获取CMD窗口句柄
  507.         HWND hCMD=GetConsoleWindow();
  508.         HDC  hDC =GetDC(hCMD);

  509.         //获取CMD窗口大小
  510.         lrRECT=&winRECT;
  511.         GetClientRect(hCMD, lrRECT);
  512.         //获取像素坐标基值
  513.         xOFFSET=lrRECT->right/2, yOFFSET=lrRECT->bottom/2;

  514.         //创建加速内存画布
  515.         HWND    hWND2=NULL;
  516.         HDC     hDC2=CreateCompatibleDC(hDC);
  517.         HBITMAP hBitmap2=CreateCompatibleBitmap(hDC, lrRECT->right, lrRECT->bottom);
  518.         SelectObject(hDC2, hBitmap2);
  519.        
  520.         //创建绘图工具
  521.         Graphics graphicsp(hDC), *graph=&graphicsp;
  522.         //创建绘图字体
  523.         FontFamily fontf(L"SimSun");
  524.         fontFAMILY=&fontf;
  525.         //创建字体画刷
  526.         SolidBrush brushp(Color(255, 255, 255, 255));
  527.         tBRUSH=&brushp;
  528.        
  529.         //初始化线条颜色
  530.         int srCOLOR=0;
  531.        
  532.         //参数接收针
  533.         char** oargv=argv;
  534.        
  535.         //参数累加器
  536.         int i=0;
  537.        
  538.         //坐标绘制态
  539.         BOOL dMARK=FALSE;

  540.         //临时变量
  541.         float tp1, tp2;

  542.         //开启主循环
  543.         while((++i)<=oargc){

  544.                 int SN=itifyWORDS(argv[i]);
  545.                 if(SN!=-1){
  546.                         if(i+SENSITIVE_ARGVS[SN]>oargc){
  547.                                         //缺少必要参数
  548.                                         fprintf(stderr, "The option '%s' needs %d parameters\n", argv[i], SENSITIVE_ARGVS[SN]);
  549.                                         exit(1);
  550.                         }
  551.                         for(anum=1; anum<=SENSITIVE_ARGVS[SN]; anum++){
  552.                                 if(oargv[i+anum][0]==SENSITIVE_WORDS[0][0]){
  553.                                         //缺少必要参数
  554.                                         fprintf(stderr, "Only %d parameters, the option '%s' needs %d parameters\n", anum-1, argv[i], SENSITIVE_ARGVS[SN]);
  555.                                         exit(1);                       
  556.                                 }
  557.                         }
  558.                
  559.                         //执行开关命令
  560.                         switch(SN)
  561.                         {
  562.                         case 0:
  563.                                 //ZOOM
  564.                                 tp1=fabsf(atof(argv[i+1])), tp2=fabsf(atof(argv[i+2]));
  565.                                 //解析ZOOM开关的隐藏功能
  566.                                 if(tp1*tp2==0){
  567.                                         if(tp2!=0){
  568.                                                 DispyCursor((DWORD)25, FALSE);
  569.                                         }else if(tp1!=0){
  570.                                                 DispyCursor((DWORD)25, TRUE );
  571.                                         }else{
  572.                                                 InvalidateRect(hCMD,  NULL, FALSE);
  573.                                                 dMARK=FALSE;
  574.                                         }
  575.                                         break;
  576.                                 }
  577.                                 InvalidateRect(hCMD,  NULL, FALSE);
  578.                                 dMARK=FALSE, srCOLOR=0, hMARK=12;
  579.                                 xZOOM=tp1, yZOOM=tp2;
  580.                                 break;

  581.                         case 1:
  582.                                 //MOVE
  583.                                 if(dMARK){
  584.                                         InvalidateRect(hCMD,  NULL, FALSE);
  585.                                         dMARK=FALSE, srCOLOR=0, hMARK=12;
  586.                                 }
  587.                                 xMOVE=atof(argv[i+1]), yMOVE=atof(argv[i+2]);
  588.                                 xOFFSET+=xMOVE, yOFFSET-=yMOVE;
  589.                                 break;

  590.                         case 2:
  591.                         case 3:
  592.                                 //PLOP||PLOT
  593.                                 if(!dMARK){
  594.                                         //调用坐标绘制函数
  595.                                         drawAXY(graph);
  596.                                         dMARK=TRUE;
  597.                                 }
  598.                                 hCOLOR=(srCOLOR++)%15;
  599.                                 drawFUN(graph, (SN==2)?TRUE:FALSE, argv[i+1], argv[i+2]);
  600.                                 break;

  601.                         default:
  602.                                 //HELP
  603.                                 fputs(HELP_INFORMATION, stderr);
  604.                                 exit(1);
  605.                         }
  606.                         i+=SENSITIVE_ARGVS[SN];
  607.                        
  608.                 //无法识别的参数
  609.                 }else{
  610.                         fprintf(stderr, "An error occurred near '%s'\n", argv[i]);
  611.                         exit(1);
  612.                 }
  613.         }

  614.         //从内存画布复制到CMD画布
  615.         //BitBlt(hDC,0,0,lrRECT->right,lrRECT->bottom, hDC2,0,0,SRCCOPY);

  616.         //清理绘图工具
  617.         DeleteObject(graph);       
  618.         DeleteObject(tBRUSH);
  619.         DeleteObject(tFONT);
  620.         DeleteObject(fontFAMILY);

  621.         //释放内存画布
  622.         ReleaseDC(NULL, hDC2);
  623.         DeleteDC(hDC2);
  624.         DeleteObject(hBitmap2);

  625.         //释放CMD 画布
  626.         ReleaseDC(hCMD, hDC);
  627.         DeleteDC(hDC);
  628. }

  629. /*************MAIN主函数入口*************/
  630. int main(int argc, char** argv)
  631. {
  632.         //初始化GdiPlus
  633.         ULONG_PTR gdipludToken;
  634.         GdiplusStartupInput gdiplusInput;
  635.         GdiplusStartup(&gdipludToken,&gdiplusInput,NULL);
  636.        
  637.         //解析开关
  638.         OptRE(argc, argv);

  639.         //关闭Gdiplus
  640.         GdiplusShutdown(gdipludToken);
  641.         return 0;
  642. }
复制代码

评分

参与人数 1威望 +6 金币 +6 贡献 +6 经验 +6 鲜花 +6 收起 理由
wayne + 6 + 6 + 6 + 6 + 6 赞一个!

查看全部评分

毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2017-2-13 11:44:02 | 显示全部楼层
厉害呀。没想到可以在 CMD 下画出 这个细腻的 图来。

好神奇的gdiplus
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2017-2-13 16:46:21 | 显示全部楼层
wayne 发表于 2017-2-13 11:44
厉害呀。没想到可以在 CMD 下画出 这个细腻的 图来。

好神奇的gdiplus

感谢点赞,代码已预留了接口,可在任何窗口绘制,同时也预留了双缓存。gdiplus并不好用,主要是为了少些代码才用gdiplus,以至于绘图速度很低下。本来是打算用虚拟画笔实现,但是我不想再增加1000行代码了,所以图了省事,就牺牲了速度。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-12-27 05:31 , Processed in 0.028216 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表