happysxyf 发表于 2017-2-12 22:47:58

原创函数绘图工具fplot.exe

本帖最后由 happysxyf 于 2017-2-12 22:53 编辑

FPLOT.EXE函数绘图工具,一直开源,从不保留。
下载:

摘要:
=============================================================================
数学函数绘图工具,支持几乎所有的数学函数表达式绘制,支持标准直角坐标、
极坐标、参数方程、参数极方程的绘制。

采用剪枝算法,具备极高绘制精度、速度,同时自动过滤间断点、无穷点。自动上色、
自动编号、自动筛选有效定义域。这是一个完全媲美GNU PLOT的工具,纯命令行操作,
更少的开关,简约而不简单。
=============================================================================

用法:
-----------------------------------------------------------------------------
fplot {arguments}...
-----------------------------------------------------------------------------
       /zoom             //设置水平缩放、垂直缩放率
       /move             //设置水平偏移、垂直偏移值
       /plo(t|p)        //待绘制自变量、因变量字串
-----------------------------------------------------------------------------

注意: 绘直角坐标用/plot,绘极坐标用/plop。

示例:
-----------------------------------------------------------------------------
fplot /zoom 3030/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 {arguments}...
-----------------------------------------------------------------------------
       /zoom   
       /move   
       /plo(t|p)
-----------------------------------------------------------------------------
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 {arguments}...\n\
-----------------------------------------------------------------\n\
       /zoom    \n\
       /move    \n\
       /plo(t|p) \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 charSENSITIVE_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};
//堆栈尺寸
#defineSTACK_SIZE      1024
//运算符栈
static char   STACK1={0};
//逆波兰栈
static char   STACK2={0};
//浮点数栈
static floatSTACK3={0};

//定义绘线属性
static floatxZOOM=50, yZOOM=50, xMOVE=0, yMOVE=0, hCOLOR=0, hPREC=1000, hMARK=12, xOFFSET=0, yOFFSET=0;

//主窗区域
RECT          winRECT={0};
LPRECT      lrRECT;

//字符串存储容器
static WCHARTainer={0};
static CHAR   FTainer ={0};

//定义颜色结构体
typedef struct{
        BYTE R;
        BYTE G;
        BYTE B;
        COLORREF VALUE;
}STRGB;
//十六色系数组
static const STRGB PARGB={
        {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;
       
        //生成逆波兰       
        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='\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;
                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();
        HDChDC =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);
                if(SN!=-1){
                        if(i+SENSITIVE_ARGVS>oargc){
                                        //缺少必要参数
                                        fprintf(stderr, "The option '%s' needs %d parameters\n", argv, SENSITIVE_ARGVS);
                                        exit(1);
                        }
                        for(anum=1; anum<=SENSITIVE_ARGVS; anum++){
                                if(oargv==SENSITIVE_WORDS){
                                        //缺少必要参数
                                        fprintf(stderr, "Only %d parameters, the option '%s' needs %d parameters\n", anum-1, argv, SENSITIVE_ARGVS);
                                        exit(1);                       
                                }
                        }
               
                        //执行开关命令
                        switch(SN)
                        {
                        case 0:
                                //ZOOM
                                tp1=fabsf(atof(argv)), tp2=fabsf(atof(argv));
                                //解析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), yMOVE=atof(argv);
                                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, argv);
                                break;

                        default:
                                //HELP
                                fputs(HELP_INFORMATION, stderr);
                                exit(1);
                        }
                        i+=SENSITIVE_ARGVS;
                       
                //无法识别的参数
                }else{
                        fprintf(stderr, "An error occurred near '%s'\n", argv);
                        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;
}

wayne 发表于 2017-2-13 11:44:02

厉害呀。没想到可以在 CMD 下画出 这个细腻的 图来。

好神奇的gdiplus

happysxyf 发表于 2017-2-13 16:46:21

wayne 发表于 2017-2-13 11:44
厉害呀。没想到可以在 CMD 下画出 这个细腻的 图来。

好神奇的gdiplus

感谢点赞,代码已预留了接口,可在任何窗口绘制,同时也预留了双缓存。gdiplus并不好用,主要是为了少些代码才用gdiplus,以至于绘图速度很低下。本来是打算用虚拟画笔实现,但是我不想再增加1000行代码了,所以图了省事,就牺牲了速度。
页: [1]
查看完整版本: 原创函数绘图工具fplot.exe