要处理一个数据,规格如下,是从EXCLE复制过来的,横轴是时间,纵轴是高度h 3          4         5          6          7         8 12.00 
0.06 2.68E+07 2.50E+07 2.63E+07 2.66E+07 2.12E+07 1.22E+07 3835000.00 
0.066 3.43E+07 3.22E+07 3.38E+07 3.41E+07 2.71E+07 1.57E+07 4967000.00 
0.072 4.23E+07 4.00E+07 4.18E+07 4.21E+07 3.34E+07 1.95E+07 6188000.00 
0.078 5.08E+07 4.82E+07 5.03E+07 5.06E+07 4.00E+07 2.35E+07 7477000.00 
0.084 5.96E+07 5.69E+07 5.91E+07 5.96E+07 4.70E+07 2.78E+07 8817000.00 
0.09 6.87E+07 6.59E+07 6.84E+07 6.88E+07 5.42E+07 3.22E+07 10200000.00 
1147程序主要代码如下:主要的思路就是找到数据中的最大和最小值,然后用她们的差值除以色阶,得到阶率,就是(MAX-MIN)/INDEX(INDEX=1147,static COLORREF Colors[1148];)这样,再通过插值可以算出两个时间间隔之间数据,并可以算出他们对应的像素,从而使用SETPIEXL画图。现在的问题是,画的图效果不太好,我估计有两个原因,一个是插值效果不好,另一个是SETPIEXL不好用。大家能不能帮忙想想如何改进呢?
还有个问题是,如果插值太多的话,画出来的图,横轴就太长了,怎么才能不管画多大的图,都是固定的大小输出呢?谢谢了,不胜感激!
CDC* pDC = pwnd->GetWindowDC();
    float temp,max,min;
int indel=1147;
    temp=m_rrpr[0][0];
int InitValue=0;
int x_left=50,y_top=750;      //绘图起点??
int x_width=800,y_height=500;//图像区域大小500,500//x_width控制X轴的长度
int x_jiange,y_jiange;
height=1400;                 //height,y_height 联合控制在图屏幕的大小
double y_range=height*m_JuLiFengBianLv/1000;
x_jiange=int(x_width/m_CeLiangShiJian-1);
y_jiange=int(y_height/(y_range+0.000000000001));
float m_pingju;
/**************
5-19  双二次插值,和移动平均 算法
**************/
//最大值
for(int i=1;i<m_CeLiangShiJian+1;i++)
for(int j=m_QiShiShuJu;j<m_ZhongZhiShuJU;j++)
{
if(temp<m_rrpr[i][j])
{
temp=m_rrpr[i][j];
}
}
    max=temp;
//求最小值
   temp=m_rrpr[0][0];
for(i=1;i<m_CeLiangShiJian+1;i++)
 for(j=m_QiShiShuJu;j<m_ZhongZhiShuJU;j++)
{
if(temp>m_rrpr[i][j])
{
temp=m_rrpr[i][j];
}
}
    min=temp;
step=(max-min)/indel;  //分辨率  每一阶像素所占的点范围
//双线性插值算法
float nx11,nx12,nx21,nx22,Red1,Red2;
for(i=1;i<m_CeLiangShiJian+1;i++)
{
for(j=m_QiShiShuJu;j<m_ZhongZhiShuJU;j++)  //双线性插值
             {
           nx11=m_rrpr[i][j];
               nx12=m_rrpr[i+1][j]; 
             for(int k=0;k<x_jiange;k++)  
                {
          Red1=nx11+(nx12-nx11)*k/(x_jiange);   //平滑过程 
        for(int m=0;m<1;m++)  
                  {
               z=Red1+(Red2-Red1)*m/1.0;
                 z=z*m_TiaoZhengXiShu;
                 index=(int)((z-InitValue)/(step+0.0000000000001));
                 index=abs(index);
                  if(index>1147)
   {  index=1147;//依据C++BUILBUDER上第一页的INDEX1取值
   }
                   if(index<0)
   {
                    index=0;
   }
                  if(index>=893)
                  {
                      Colors[index]=RGB(255,1148-index,0);    //红 橙 黄
                  }
                   if((index>=638)&&(index<893))
                  {
                      Colors[index]=RGB(index-638,255,0);        // 绿  草绿  黄
                  }
              if((index>=383)&&(index<638))
                  {
                    Colors[index]=RGB(0,255,638-index);          //   绿  青绿 青蓝
                  }
                  if((index>=128)&&(index<383))
                  {
                     Colors[index]=RGB(0,index-128,255);          //    深蓝  浅蓝  青蓝
  }
              if((index>=0)&&(index<128))
  { 
                     Colors[index]=RGB(128-index,0,255);               //深蓝   紫
  } 
            pDC->SetPixel(i*x_jiange+k+x_left,
  y_top-j*y_height/height,Colors[index]);
                  }
                 }
  }      
}

解决方案 »

  1.   

    GradientFill来画,填充的区域效果比较好。
      

  2.   

    一个是SETPIEXL不好用。------ 这个微软给的,只能这样了,我也不知要如何才叫好用啊。 
    还有个问题是,如果插值太多的话,画出来的图,横轴就太长了,怎么才能不管画多大的图,都是固定的大小输出呢?------------只要使用一个常数表示屏幕中你想设置的图形的宽度,如int const nWidth=2000; 然后根据你的横轴的数据量(应该是项数吧?)来等分出一个值,或者叫比例尺或转换率。这样来画就可以了。而且你说的效果不太好,我都没弄明白如何的效果不太好?你希望的效果是如何的。这个说清楚一些,必要时上传个图我想可以帮助大家对你的要求的理解。而且你要的这个图好像也是有现成控件可以实现的。你只要将转换后的值赋给它就可以了。不过还是涉及到插值的问题(你需要向它提供的是计算后的值)。
      

  3.   

     左边的图是用上述代码画的,右边的是别人画的。应当是右边的色彩更鲜艳点吧。
    数据没给清楚,重新写一下,呵呵。对不住了
         3           4           5          6           7            8          9 
         2.68E+07    2.50E+07   2.63E+07    2.66E+07    2.12E+07     1.22E+07   3835000.00 
         3.43E+07    3.22E+07   3.38E+07    3.41E+07    2.71E+07     1.57E+07   4967000.00 
         .            .         .           .           .            .          .                                .
         .            .         .           .           .            .          .        
         .            .         .           .           .            .          .                                                                                                  
    这样应当没问题了吧
    横轴太长这个问题还有个情况是:如果横轴的数据点多呢?怎么在固定的区域画出来?比如9完了还有10,11,这样按照大哥的方法还是不行吧。(大哥的方法是固定3,4,5,6,7,.....的插值点数,对吧)再比如,如果纵轴的点数更多点呢?这样用SETPIEXL画的图,不是很大了么?多谢指教。呵呵
      

  4.   

    说明:这是我最近用来画图的一个函数,可能会帮上你的忙,其中stress_time* pdata是一个
    指向数据区的指针,当然用你自己定义的数据类型,long numbers是要绘制的数据的个数。
    void CTestDlg::DrawCurve(CDC* dc,stress_time* pdata,long numbers)
    {
    POINT vector; //绘图区左上角坐标
    vector.x=40;
    vector.y=20;
    //#define bitsOfwidth 500 //绘图区宽度
    //#define bitsOfheight 300 //绘图区高度

    /*************************************数据准备*****************************************/
    float maxStress,minStress,maxTimer,minTimer;
    maxStress=pdata->m_stress;
    minStress=pdata->m_stress;
    maxTimer=pdata->m_timer;
    minTimer=pdata->m_timer;
    struct point{float x;float y;};
    point data[bitsOfwidth];
    for(int i=0;i<bitsOfwidth;i++)
    {
    data[i].x=(pdata+long(i*numbers/bitsOfwidth))->m_timer;
    data[i].y=(pdata+long(i*numbers/bitsOfwidth))->m_stress;
    if(data[i].x>maxTimer)maxTimer=data[i].x;
    if(data[i].x<minTimer)minTimer=data[i].x;
    if(data[i].y>maxStress)maxStress=data[i].y;
    if(data[i].y<minStress)minStress=data[i].y;
    }
    POINT position[bitsOfwidth];
    for(i=0;i<bitsOfwidth;i++)
    {
    position[i].x=long((data[i].x-minTimer)*bitsOfwidth/(maxTimer-minTimer)+vector.x);
    position[i].y=long(bitsOfheight-(data[i].y-minStress)*bitsOfheight/(maxStress-minStress)+vector.y);
    }
    /**************************************************************************************//*************************************背景绘制*****************************************/
    CPen* oldpen;
    CPen RedPen(PS_SOLID,1,RGB(250,0,0));
    CPen GreenPen(PS_SOLID,1,RGB(0,200,0));
    CPen BluePen(PS_SOLID,1,RGB(100,100,0));
    RECT rect;
    rect.bottom=vector.y+bitsOfheight+40;
    rect.top=0;
    rect.left=0;
    rect.right=vector.x+bitsOfwidth+20;
    CBrush BlueBrush(RGB(200,200,200));
    dc->FillRect(&rect,&BlueBrush);
    oldpen=dc->SelectObject(&GreenPen);
    dc->MoveTo(vector);
    dc->LineTo(vector.x,vector.y+bitsOfheight);
    dc->LineTo(vector.x+bitsOfwidth,vector.y+bitsOfheight);
    dc->LineTo(vector.x+bitsOfwidth,vector.y);
    dc->LineTo(vector);
    dc->SelectObject(&BluePen);
    for(i=0;i<9;i++)
    {
    dc->MoveTo(vector.x,vector.y+(i+1)*bitsOfheight/10);
    dc->LineTo(vector.x+bitsOfwidth,vector.y+(i+1)*bitsOfheight/10);
    dc->MoveTo(vector.x+(i+1)*bitsOfwidth/10,vector.y);
    dc->LineTo(vector.x+(i+1)*bitsOfwidth/10,vector.y+bitsOfheight);
    }
    dc->SetTextColor(RGB(0,0,250));
    dc->SetBkMode(TRANSPARENT);
    long x,y;
    int l;
    char st[30];
    for(i=0;i<11;i++)
    {
    sprintf(st,"%.1f",minTimer+i*(maxTimer-minTimer)/10);
    l=strlen(st);
    y=vector.y+bitsOfheight+10;
    x=vector.x+i*bitsOfwidth/10-l*3;
    dc->TextOut(x,y,st);
    }
    for(i=0;i<11;i++)
    {
    sprintf(st,"%.1f",minStress+i*(maxStress-minStress)/10);
    l=strlen(st);
    y=vector.y+bitsOfheight-(i*bitsOfheight/10)-10;
    x=vector.x-l*8;
    dc->TextOut(x,y,st);
    }
    /**************************************************************************************//*************************************曲线绘制*****************************************/
    dc->SelectObject(&RedPen);
    for(i=0;i<(bitsOfwidth-1);i++)
    {
    dc->MoveTo(position[i]);
    dc->LineTo(position[i+1]);
    } dc->SelectObject(oldpen);
    }