登录 免费注册 首页 | 行业黑名单 | 帮助
维库电子市场网
技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统
驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe

关于折线变曲线的c语言实现

作者:yuke 栏目:单片机
关于折线变曲线的c语言实现
    当然是在单片机环境下。将一条折线转换为平滑的曲线,即:屏幕上有n(假设n=5)个点,分别为(x0,y0)……(x4,y4),直接连起来就是折线了。现在用一条平滑的曲线把他们连起来,使之成为一条曲线。
    由于时间关系,明天再把我的思路补上来,先听听各位前辈同仁们的意见。

2楼: >>参与讨论
lanmp
插值?
 
3楼: >>参与讨论
isoar
贝赛尔函数,这东西不是有现成的吗?
 
4楼: >>参与讨论
yuke
bessel? 不熟~~
    插值法试过,不过有10个点的话,就是个9次函数~~~~~~受不了啊。
    暂时我是按隔4个点画条斜线的办法,斜率缓慢变化(比如第一个点到第二个点之间的曲线画法:若2,3点连线的斜率绝对值大于头两点连线斜率绝对值,则从第一点画一条斜线,横坐标增加4,斜率0,逐渐变化斜率,从x0+4开始画下个短斜线。控制好最后短斜线的斜率等于1,2点连线的斜率。)
    

5楼: >>参与讨论
stintair
可以采用Bezier或者B样条曲线
采用三次曲线差值效果些,可保证曲线及斜率可微。

6楼: >>参与讨论
IceAge
也可使用最小二乘法,求出拟合多项式
公式相当简单,只是涉及矩阵求逆,如果使用matlab, mathcad 则很容易。
Excel 里似乎有最小二乘法和Bezier的函数

7楼: >>参与讨论
liudewei
MATLAB几分钟搞定
 
8楼: >>参与讨论
雷风
直接试试Excel
同IceAge

9楼: >>参与讨论
yuke
这是我找的一段程序,大家可以参考下,不过效果稍欠
其中Pxy[NP][2]为给定点:


#include <graphics.h>
#include <conio.h>

#define NX 21
#define NP 8
#define SCRW 620
#define SCRH 460

float Ms[4][4]={{2,-2,1,1},{-3,3,-2,-1},
        {0,0,1,0},{1,0,0,0}};
float Rxy[NP][2];
float Pxy[NP][2]={{0,0},{-3,2.5},{-2,5},{0.25,4},{-0.25,4},{2,5},{3,2.5},{0,0}};
float pxbl,pybl,pxc,pyc;

void Qfun(float *x, float *y, float t,int k) {
    float pw[4];
    int i;
    for (i=0;i<4;i++){
       pw[i]=t*t*t*Ms[0][i]+t*t*Ms[1][i]+t*Ms[2][i]+Ms[3][i];
    }
    *x=pw[0]*Pxy[k][0]+pw[1]*Pxy[k+1][0]+pw[2]*Rxy[k][0]+pw[3]*Rxy[k+1][0];
    *y=pw[0]*Pxy[k][1]+pw[1]*Pxy[k+1][1]+pw[2]*Rxy[k][1]+pw[3]*Rxy[k+1][1];
}

void Draw(int i) {
     float tlen=1.0/(NX-1);
     float ox,oy,x,y,t;
     Qfun(&ox,&oy,0.0,i);
     t=0;
     while(t<=1.0){
      t+=tlen;
     Qfun(&x,&y,t,i);
     LINE((ox-pxc)*pxbl+SCRW/2,SCRH/2-(oy-pyc)*pybl,
          (x-pxc)*pxbl+SCRW/2,SCRH/2-(y-pyc)*pybl);
     ox=x; oy=y;
     }
}

void CalcRxy() {
   float beta[NP];
   int i;
   for (i=1;i<NP-1;i++) {
       Rxy[i][0]=3*(Pxy[i+1][0]-Pxy[i-1][0]);
       Rxy[i][1]=3*(Pxy[i+1][1]-Pxy[i-1][1]);
   }
   beta[1]=4.0;
   for (i=2;i<NP-1;i++) {
      beta[i]=4.0-(1/beta[i-1]);
      Rxy[i][0]=Rxy[i][0]-(1/beta[i-1])*Rxy[i-1][0];
      Rxy[i][1]=Rxy[i][1]-(1/beta[i-1])*Rxy[i-1][1];
   }
  Rxy[NP-2][0]=Rxy[NP-2][0]/beta[NP-2];
  Rxy[NP-2][1]=Rxy[NP-2][1]/beta[NP-2];
  for (i=NP-3;i>0;i--) {
      Rxy[i][0]=(Rxy[i][0]-Rxy[i+1][0])/beta[i];
      Rxy[i][1]=(Rxy[i][1]-Rxy[i+1][1])/beta[i];
  }
}

void Hermite() {
    int i,j;
    float xmax,xmin,ymax,ymin;
    xmax=xmin=Pxy[0][0], ymax=ymin=Pxy[0][1];
    for (i=0;i<NP;i++){
      if (xmin>Pxy[i][0]) xmin=Pxy[i][0];
      if (xmax<Pxy[i][0]) xmax=Pxy[i][0];
      if (ymin>Pxy[i][1]) ymin=Pxy[i][1];
      if (ymax<Pxy[i][1]) ymax=Pxy[i][1];
    }
    pxbl=0.7*SCRW/(xmax-xmin); pybl=0.7*SCRH/(ymax-ymin);
    pxc=(xmax+xmin)/2.0; pyc=(ymax+ymin)/2.0;
    if (pxbl<pybl) pybl=pxbl;
    else pxbl=pybl;

    Rxy[0][0]=-3; Rxy[0][1]=0;
    Rxy[NP-1][0]=-3; Rxy[NP-1][1]=0;
    CalcRxy();
    for (i=0;i<NP-1;i++) {
      Draw(i);
//      putpixel((Pxy[i][0]-pxc)*pxbl+SCRW/2,
//           SCRH/2-(Pxy[i][1]-pyc)*pybl,4);
      outtextxy((Pxy[i][0]-pxc)*pxbl+SCRW/2-3,
           SCRH/2-(Pxy[i][1]-pyc)*pybl-4,"o");
      outtextxy((Pxy[i+1][0]-pxc)*pxbl+SCRW/2-3,
           SCRH/2-(Pxy[i+1][1]-pyc)*pybl-4,"o");
      getch();
    }
}

void main (void){
   int gd=0,gm;
   initgraph(&gd,&gm,"..\\bgi");
   Hermite();
}


参与讨论
昵称:
讨论内容:
 
 
相关帖子
请诸位大师推荐几款28PIN的51系列的单片机芯片?
51 单片机 加密方法
请问怎么在lcd上显示时钟的时针和分针
[求助]PC串口接受的16进字与单片机发送的不一样
keil下写程序的一个怪问题,请指教,谢谢
免费注册为维库电子开发网会员,参与电子工程师社区讨论,点此进入


Copyright © 1998-2006 www.dzsc.com 浙ICP证030469号