本程序通过x,y坐标的两次拉格朗日插值
实现非简单曲线的绘制
通过鼠标取点,简单易用
欢迎提出建议
>>>>本程序在winxp&&tc2.0环境下调试通过<<<<
(把下列文件分别单独存放,
并拷贝至tc主目录下编译line102.c即可。
包含文件:
line102.c
graph.h
bioskey.h)
!!!以下是文件line102.c
#include<dos.h>
#include<graphics.h>
#include<stdio.h>
#include<bios.h>
#include<conio.h>
#include"bioskey.h"
#include"graph.h"
/*////////////////////////////////////////////////////////////////////*/
#define xmax 640
#define ymax 480
/*////////////////////////////////////////////////////////////////////*/
typedef struct point
{
int x,y;
struct point*f,*p;
}POINT;
/*////////////////////////////////////////////////////////////////////*/
void cross(int x,int y,int length);
void arcline(int n);
void doarcline(POINT*p,int x,int y,int tn,int style);
POINT*getpoint(POINT*p,int index);
int getsize(POINT*p);
/*////////////////////////////////////////////////////////////////////*/
void main()
{
int gd=DETECT,gm;
int x,y,b,t=3,color=9,bkcolor=10;
char s1[20],s2[20],s3[20];
initgraph(&gd,&gm,"");
initm(0,0,xmax,ymax);
loop: setcolor(color);
setfillstyle(1,bkcolor);
bar(0,0,xmax,ymax);
rectangle(1,1,xmax-2,ymax-2);
rectangle(0,0,xmax-1,ymax-1);
loop1: sprintf(s1," point:%d",t);
sprintf(s2," color:%d",color);
sprintf(s3,"bkcolor:%d",bkcolor);
setcolor(15-bkcolor);
setfillstyle(1,10);
bar(6,6,92,46);
setcolor(9);
rectangle(6,6,92,46);
outtextxy(10,10,s1);
outtextxy(10,20,s2);
outtextxy(10,30,s3);
setcolor(color);
setlinestyle(0,0,0);
while(1)
{
int key;
key=0;
arcline(t);
if(kbhit())
{
key=bioskey(0);
switch(key)
{
case bios_up:if(t<10)
{
t++;
goto loop1;
}break;
case bios_dn:if(t>3)
{
t--;
goto loop1;
} break;
case bios_left:color=(color+15)%16;goto loop1;
case bios_right:bkcolor=(bkcolor+1)%16;goto loop;
case bios_c:;
case bios_C:goto loop;
case bios_esc:closegraph();return;
default:break;
}
}
}
}
/*////////////////////////////////////////////////////////////////////*/
void cross(int x,int y,int length)
{
opline(x-length/2,y,x+length/2+1,y);
opline(x,y-length/2,x,y+length/2+1);
}
void arcline(int n)
{
int i;
POINT *p0;
int x=0,y=0,x0,y0;
double tn=100;
int length=8;
if(n<3)n=3;
cross(x,y,length);
p0->f=0,p0->p=0;
for(i=0;i<n;i++)
{
int b,did,x2,y2;
POINT *p;
p=malloc(sizeof(POINT));
b=0,did=0;
while(b==0)
{
int x1,y1;
x1=x,y1=y;
readm(&x,&y,&b);
if(x1!=x||y!=y1)
{
cross(x,y,length);
cross(x1,y1,length);
}
if(kbhit())
{
cross(x1,y1,length);
return;
}
}
if(i==1)
{
x0=p0->f->x,y0=p0->f->y;
opline(x0,y0,x,y);
}
else if(i==2)
{
int x1,y1;
POINT*tp=getpoint(p0,2);
x1=tp->x,y1=tp->y;
opline(x0,y0,x1,y1);
}
else if(i>2)
doarcline(p0->f,0,0,(int)tn,0);
{
POINT *p1;
int place;
if(i<2)place=i;
else place=i-1;
p1=getpoint(p0,place);
p->p=p1,p->f=p1->f;
p->x=x,p->y=y;
if(p->f!=0)
p->f->p=p;
p1->f=p;
}
while(b!=0&&i>0)
{
int x1,y1;
x1=x,y1=y;
readm(&x,&y,&b);
if(x1!=x||y!=y1)
{
cross(x1,y1,length);
cross(x,y,length);
}
p->x=x,p->y=y;
if(x!=x1||y!=y1||did==0)
{
/*if(i==0)oppixel(x,y);*/
if(i==1)
{
opline(x0,y0,x1,y1);
opline(x0,y0,x,y);
}
else if(i>1)
{
/* p->x=x1,p->y=y1;*/
int t;
t=did==0?0:2;
p->x=x,p->y=y;
doarcline(p0->f,x1,y1,(int)tn,t);
/* doarcline(p0->f,0,0,(int)tn,0);*/
}
if(did==0)did=1;
}
}
}
doarcline(p0->f,0,0,tn,0);
cross(x,y,length);
doarcline(p0->f,0,0,tn,1);
{
POINT *t=p0;
for(;n>0;n--)
{
t=getpoint(p0,n);
free(t);
}
}
}
void doarcline(POINT*p,int x,int y,int tn,int style)/*点链表,旧坐标,精度,类型*/
{
double t,k,arcx,arcy,arcx1,arcy1;
int tx=p->x,ty=p->y,tx1=tx,ty1=ty;
double rt;
double tn0=(double)tn;
double i=(double)getsize(p)-1;
for(rt=0;rt<=tn0;rt++)
{
t=rt/tn0*i;
arcx=0,arcy=0;
arcx1=0,arcy1=0;
for(k=0;k<=i;k++)
{
double fx,fy,fx1,fy1,L,j;
L=1;
fx=(double)(getpoint(p,(int)k)->x);
fy=(double)(getpoint(p,(int)k)->y);
fx1=fx,fy1=fy;
if(k==i-1)
fx1=(double)x,fy1=(double)y;
for(j=0;j<=i;j++)
if(j!=k)
L*=(t-j)/(k-j);
arcx+=fx*L;
arcy+=fy*L;
arcx1+=fx1*L;
arcy1+=fy1*L;
}
if(style==1)
line(tx,ty,(int)arcx,(int)arcy);
else
{
opline(tx,ty,(int)arcx,(int)arcy);
if(style==2)
opline(tx1,ty1,(int)arcx1,(int)arcy1);
}
tx=(int)arcx,ty=(int)arcy;
tx1=(int)arcx1,ty1=(int)arcy1;
}
}
POINT*getpoint(POINT*p,int index)
{
POINT*t=p;
while(index>0&&t->f!=0)
{
index--;
t=t->f;
}
return t;
}
int getsize(POINT*p)
{
int size=0;
while(getpoint(p,size)->f!=0)
size++;
return size+1;
}
/*end of line102.c*/
!!!以下是文件graph.h
#if !defined graphheadfile
#define graphheadfile
/***************************************************************/
#include <graphics.h>
#include <conio.h>
#include <math.h>
#include <dos.h>/*调用函数:int86()'注:中断'鼠标操作时用*/
union REGS regs;/*鼠标操作时用*/
int color[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
void*mimage;
/***************************************************************/
void arrowhead(int x,int y);/*箭头*/
void buttonup(int sx,int sy,int mx,int my);/*绘制按钮(抬起)*/
void buttondn(int sx,int sy,int mx,int my);/*绘制按钮(按下)*/
void clbutton(int sx,int sy,int mx,int my);/*清除在点(sx,sy),(mx,my)之间矩形区域内的按钮*/
void clwinrect(int sx,int sy,int mx,int my);/*清除在点(sx,sy),(mx,my)之间矩形区域内的windows框*/
void initm(int xmi,int ymi,int xma,int yma);/*初始化设定鼠标移动范围*/
void loadmimage(int x,int y);
void menupad(int sx,int sy,int mx,int my,int type);/*绘制菜单面板type 0:无标题栏;type 1:有标题栏*/
int messagebox(int x0,int y0,int x1,int y1,char*message);/*消息提示框*/
void movem(int x,int y);/*手动移动鼠标*/
void opbar(int x0,int y0,int x1,int y1);/*反色方条*/
void oppixel(int x,int y);/*在(x,y)处绘制反色点*/
void opline(int x0,int y0,int x1,int y1);/*绘制反色线(包含oppixel)*/
void oprect(int x0,int y0,int x1,int y1);/*反色矩形*/
void putmimage(int x,int y);
void putnumxy(int x,int y,float num,int type);/*在屏幕上打印数字*/
void readm(int*x,int*y,int*button);/*读取鼠标状态*/
void winrect(int sx,int sy,int mx,int my);/*在点(sx,sy),(mx,my)之间的矩形区域,添加一个模拟Windows的框*/
/***************************************************************/
void oparrowhead(int x,int y)/*反色箭头*/
{
opline(x,y,x+10,y+10);
opline(x+10,y+10,x+5,y+10);
opline(x+6,y+11,x+9,y+18);
opline(x+6,y+17,x+3,y+11);
opline(x+3,y+12,x,y+15);
opline(x,y+15,x,y);
oppixel(x+7,y+18);
}
void arrowhead(int x,int y)/*箭头*/
{
int n;
setcolor(15);
setlinestyle(0,0,1);
for(n=1;n<10;n++)
line(x+n,y+n,x+n,y+9);
for(n=12;n>9;n--)
line(x+13-n,y+n,x+13-n,y+9);
line(x+7,y+16,x+4,y+10);
line(x+6,y+16,x+3,y+10);
setcolor(0);
line(x,y,x+10,y+10);
line(x+10,y+10,x+5,y+10);
line(x+8,y+16,x+5,y+10);
line(x+6,y+17,x+3,y+11);
line(x+3,y+11,x,y+14);
line(x,y+14,x,y);
line(x+7,y+17,x+8,y+17);
}
/*-------------------------------------------------------------*/
void buttonup(int sx,int sy,int mx,int my)/*在点(sx,sy),(mx,my)之间的矩形区域内,添加一个突起的按钮*/
{ /*此函数与前一个函数相似,此处不加注释*/
if(my<sy+17)my=sy+17;
if(mx<sx+30)mx=sx+30;
/* setfillstyle(1,7);
bar(sx,sy,mx,my);*/
/*以下模拟Windows按钮*/
setcolor(15);
rectangle(sx,sy,mx,my);
setcolor(7);
rectangle(sx+1,sy+1,mx-1,my-1);
setcolor(0);
line(sx,my,mx,my);
line(mx,sy,mx,my);
setcolor(8);
line(sx+1,my-1,mx-1,my-1);
line(mx-1,sy+1,mx-1,my-1);
}
/*-------------------------------------------------------------*/
void buttondn(int sx,int sy,int mx,int my)/*在点(sx,sy),(mx,my)之间的矩形区域内,添加一个按下的按钮*/
{
if(my<sy+17)my=sy+17; /*保证纵坐标最大�