数值微分(DDA)法画直线

/*编译环境 DEVcpp + EasyX*/
#include<stdio.h>
#include <graphics.h> // 引用图形库头文件
#include<iostream>
#include<math.h>
using namespace std;

const int mySIZE=20;//大小设置
const int myWidth=32*mySIZE;
const int myHeight=24*mySIZE;

void DDA_drawLine(int x0,int y0, int x1,int y1);//DDA直线生成算法
void mathDrawLine(int origin_x, int origin_y, int x0,int y0, int x1,int y1);//数学坐标转屏幕坐标
void mathDrawAry(int origin_x, int origin_y, int x0,int y0, int x1,int y1);//数学坐标画射线


int main()
{
//输入数据
int origin_x, origin_y, line_num;//原点位置
int points[20][4];
cout<<"输入原点位置(屏幕坐标,建议:"<<(myWidth>>1)<<" "<<(myHeight>>1)<<")"<<endl;
cin>>origin_x>>origin_y;
cout<<"输入线段数量"<<endl;
cin>>line_num;
cout<<"输入所有线段(数学坐标,x0 y0 x1 y1)"<<endl;
for(int i=0; i<line_num; ++i){
cin>>points[i][0]>>points[i][1]>>points[i][2]>>points[i][3];
}

//绘图窗口初始化
initgraph(myWidth, myHeight,1); // 创建绘图窗口
setfillcolor(WHITE);fillrectangle(0,0,myWidth, myHeight);//底色
setlinecolor(BLACK); //线色
setbkcolor(WHITE);//背景色
settextcolor(BLACK);//字体色

//绘图
mathDrawAry(origin_x,origin_y,-((myWidth>>1)-2*mySIZE),0,((myWidth>>1)-2*mySIZE),0);//坐标轴x
outtextxy(origin_x+((myWidth>>1)-2*mySIZE),origin_y,'x');
mathDrawAry(origin_x,origin_y,0,-((myHeight>>1)-2*mySIZE),0,((myHeight>>1)-2*mySIZE));//坐标轴y
outtextxy(origin_x,origin_y-((myHeight>>1)-2*mySIZE),'y');
for(int i=0; i<line_num; ++i){
mathDrawAry(origin_x,origin_y,points[i][0],points[i][1],points[i][2],points[i][3]);//画线
}

//结束绘图
getchar();
getchar();
closegraph(); // 关闭绘图窗口
return 0;
}


void DDA_drawLine(int x0,int y0, int x1,int y1)//DDA直线生成算法
{
int delta_x=x1-x0,delta_y=y1-y0;
//特殊情况
if(delta_x==0){
if(delta_y<0){
delta_y=y0;
y0=y1;
y1=delta_y;
}
for(;y0<=y1;++y0)
putpixel(x0,y0,BLACK);
return ;
}
//一般情况
double k;
double x,y;
if(abs(delta_x)>=abs(delta_y)){//以x为基准 (k绝对值<1)
if(delta_x<0){
DDA_drawLine(x1,y1,x0,y0);return;//掉头
}
k=double(delta_y)/delta_x;//可正可负
for( x=x0,y=y0; x<=x1; ++x){
y+=k;
putpixel(x,y,BLACK);
}
}
else{//以y为基准 (k绝对值>1)
if(delta_y<0) {
DDA_drawLine(x1,y1,x0,y0);return;//掉头
}
k=double(delta_x)/delta_y;//可正可负
for(x=x0,y=y0;y<y1;++y){
x+=k;
putpixel(x,y,BLACK);
}
}
}

 


void mathDrawLine(int origin_x, int origin_y, int x0,int y0, int x1,int y1)//数学坐标转屏幕坐标
{
x0 = x0+origin_x;
x1 = x1+origin_x;
y0 = origin_y-y0;
y1 = origin_y-y1;
DDA_drawLine(x0,y0,x1,y1);
}
void mathDrawAry(int origin_x, int origin_y, int x0,int y0, int x1,int y1)//数学坐标画射线
{
//计算角度
const double PI=3.1415926535;
const double delta_ang=PI/12;//15度
double ang;
int delta_x=x1-x0,delta_y=y1-y0;
if(delta_x==0){
if(delta_y>=0)
ang=1.5*PI;
else
ang=0.5*PI;
}
else if(delta_x>0){// 2,3象限
ang=atan(double(delta_y)/delta_x)+PI;
}
else{//1,4象限
ang=atan(double(delta_y)/delta_x);
}
//计算坐标,画线
mathDrawLine(origin_x,origin_y,x0,y0,x1,y1);//原直线
int x2,y2,len;
len=sqrt(delta_y*delta_y+delta_x*delta_x)/10;
x2=x1+cos(ang+delta_ang)*len;
y2=y1+sin(ang+delta_ang)*len;
mathDrawLine(origin_x,origin_y,x1,y1,x2,y2);//箭头线1
x2=x1+cos(ang-delta_ang)*len;
y2=y1+sin(ang-delta_ang)*len;
mathDrawLine(origin_x,origin_y,x1,y1,x2,y2);//箭头线2
}

 /*测试数据

320 240
8
-150 50 50 150
50 150 150 -50
150 -50 -50 -150
-50 -150 -150 50
-150 50 50 50
50 150 50 -50
150 -50 -50 -50
-50 -150 -50 50

*/

posted @ 2022-10-27 16:35  xun道者  阅读(91)  评论(0)    收藏  举报