两点直线算法
❶ 直线扫描算法(个人总结,仅供参考)
直线扫描算法主要包含三种算法,DDA算法、中点画线算法、Bresenham直线算法。
这三种算法都要事先要确定两个端点(起点和终点),从起点开始每次走一步,每走一步画一个点,直至到达终点。
这个前提也比较好理解,因为如果朝斜率大的方向走,可能没走几步就走完了,那画出来的直线就是离散的。
以下我们只讨论朝x方向移动的情况。(y方向的情况是一样的)
DDA算法实际上是根据 斜截式直线方程 来画的。
但这么做实际上是比较消耗性能的,因为斜截式方程, 它涉及到了乘法运算 。因此我们需要通过 增量思想 对它进行优化。
这样转换后,我们就可以根据当前的位置来找到下一步的位置,且每次计算只需要进行一次 浮点的加法运算 ,一次四舍五入取整即可。
中点画线算法实际上是根据 一般式直线方程 来画的。它是通过判断中点在直线的下方还是上方,来决定下一步的坐标位置。
但这样也是非常消耗性能的,把中点带入F(x, y)中,会涉及到2个乘法,4个加法。我们依然可以通过增量的方式来对它进行优化。
这样我们就优化到每次只需要一次 整数加法 即可,且还不需要四舍五入。因此它要更优于DDA算法。
Breseham算法是通过比较d(交点与交点下方最近的点的距离)来进行选择的。d每次按照k的大小增加。
但这么做依旧和DDA算法一样,会涉及到浮点数k的加法。我们可以通过 换元的方式 对它进行下优化。
这样就能使得每次进行一次或两次的 整数加法运算 ,不需要四舍五入。效率高于DDA,低于中点画线算法。
但Bresenham算法不依赖直线方程,使得它能有更宽泛的适用范围。
❷ 已知平面直角坐标系中的两点A(-1,0),B(3,2),写出求直线AB的方程的一个算法
由题:因为向量AB=(4,2)
所以斜率2/4=1/2
过B(3,2)
所以2=3/2+b
b=1/2
所以:y=x/2+1/2
❸ 两点关于Y=kX+B直线对称的算法
己知一点坐标A,另一点B关于Y=kX+B的直线轴对称
,那么联结AB,AB与直线Y=kX+B垂直,那么我们可以设AB所在的直线的解析式为Y=-1/kX+C,垂直斜率相乘等于-1。把A代入可求出C,B就很方便求了,A到直线与B到直线的距离相等来求
❹ 已知直角坐标系中两点A(-1,0),B(0,2),写出求直线AB的方程的两个算法。
我是文盲,只好抄袭,你们只能鄙视我。。。
点B是直线在y轴的截距
设y=kx+2,将(-1,0)代入
k=2
直线y=2x+2
点A是直线在x轴截距
设x=ny-1
将(0,2)代入
n=1/2
x=1/2y-1
即y=2x+2
回答者:
78101557
|
十六级
|
2011-8-24
19:09
一是用截距式:设x/a+y/b=1
;然后两点代入得-x+y/2=1
二是用斜截式:设y=kx+b:然后两点代入得;y=2x+2
❺ 已知平面直角坐标系中的两点A(1,0),B(3,2)写出求直线B的方程的一个算法
解:已知两点的坐标,求直线方程最直观的一个算法就是用两点式的直线方程。
(y--0)/(2--0)=(x--1)/(3--1)
y/2=(x--1)/2
y=x--1
即: x--y--1=0.
❻ 直线的生成算法有哪些
第一种算法:DDA直线生成算法是一种使用微分方程生成直线的算法,又称作数值微分法。该算法的基本思想是:根据斜率确定增量最大的方向,每次迭代时均在该方向上走一步,然后根据直线方程计算出另一方向上的值,对其四舍五入后得到像素坐标。第二种算法:Bresenham直线生成算法与DDA算法类似,每次迭代时均在增量最大方向上走一步,并计算决策参数,根据决策参数确定像素坐标。算法的巧妙之处在于采用了增量计算,使得对于每一列,只要检查误差量的符号,就可以确定该下一列的像素坐标。
❼ 求两直线交点坐标算法的问题(高手进)
(1)设定直线1的倾角a1,及其上一点(p1,q1);设定直线2的倾角a2,及其上一点(p2,q2)
(2)判断是否a1=a2
如果是,输出"两直线平行",程序结束
如果否,程序继续
(3)判断是否a1=90
如果是,计算x=p1,k2=tana2,y2=k2*x+q2-k2*p2,输出x,y2,程序结束
如果否,程序继续
(4)判断是否a2=90
如果是,计算x=p2,k1=tana1,y1=k1*x+q1-k1*p1,输出x,y1,程序结束
如果否,程序继续
(5)计算k1=tana1,k2=tana2
计算x=(q2-k2*p2-q1+k1p1)/(k1-k2)
y=k2*x+q2-k2*p2
输出x,y
程序结束
❽ 如何由一个点绘出一个任意两点的线,求算法,想用单片机显示器画线。
把C语言的子函数给你。参考一下,附送圆形和矩形。
/**********************************
两点间画直线:
x1<x2<127,y1<y2<64
***********************************/
void Draw_line(unsigned char x1,y1,x2,y2)
{
unsigned char i;
for(i=x1;i<x2+1;i++)
Draw_dots(i,(y2-y1)*(i-x1)/(x2-x1)+y1,2);
}
/**********************************
画圆:
(x,y)为圆心,r为半径
***********************************/
void Draw_circle(unsigned char x,y,r)
{
unsigned char i;
for(i=x-r;i<x+r+1;i++)
{
Draw_dots(i,y-sqrt(r*r-(x-i)*(x-i)),2);
Draw_dots(i,y+sqrt(r*r-(x-i)*(x-i)),2);
}
}
/**********************************
两矩形:
(x1,y1)为矩形左上角坐标点
(x2,y2)为矩形右上角坐标点
***********************************/
void Draw_retic(uchar x1,uchar y1,uchar x2,uchar y2)//画正方形,x1,y1为左上角坐标,x2,y2为右下角坐标
{
uchar i;
for(i=0;i<=x2-x1;i++)
{
Draw_dots(x1+i,y1,2);
Draw_dots(x1+i,y2,2);
}
for(i=0;i<=y2-y1;i++)
{
Draw_dots(x1,y1+i,2);
Draw_dots(x2,y1+i,2);
}
}
//画点函数
void Draw_dots(uchar x,uchar y,uchar color)
{
uchar x_byte;
uchar x_bit;
uchar Temp_data; //暂时存放从LCD读出的数据
x_byte=(y>>3); //计算出该点属于哪个字节
x_bit=y-(x_byte<<3); //属于字节的哪一位
if(x>63) //x>63则显示在右半屏
{
SelectScreen(2);
x=x-64;
}
else //显示在左半屏
{
SelectScreen(1);
}
Set_page(x_byte); //设置行地址
Set_column(x); //设置列地址
Temp_data=Read_LCD(); //先读出没打点前LCD中的数据
switch(color)
{
case 0x01 : Temp_data &= ~(1<<x_bit);break; //擦除
case 0x02 : Temp_data ^= (1<<x_bit); break; //反白
case 0x03 : Temp_data |= (1<<x_bit); break; //画点
default : break;
}
Set_page(x_byte);
Set_column(x);
write_LCD_data(Temp_data); //将处理后的数据送到LCD中显示
}
❾ c++如何画直线
包含windows.h,里面有一个SetPixel方法,画线常用算法有三种dda,中点画线Bresenham画线->_->
刚把三种都写了下
voidCDDALineView::drawDDALine(CDC*pDC,intx0,inty0,intx1,inty1,COLORREFcolor)
{
floatdeltax,deltay,x,y;
intsteps=max(abs(x1-x0),abs(y1-y0));
deltax=(x1-x0)/steps;
deltay=(y1-y0)/steps;
x=x0;
y=y0;
pDC->SetPixel((int)(x+0.5),(int)(y+0.5),color);
for(inti=0;i<steps;i++)
{
x+=deltax;
y+=deltay;
pDC->SetPixel((int)(x+0.5),(int)(y+0.5),color);
}
}
//preCondition:x0<x1
voidCDDALineView::MidpointLine(CDC*pDC,intx0,inty0,intx1,inty1,COLORREFcolor)
{
inta=y0-y1;
intb=x1-x0;
intc=x0*y1-x1*y0;
floatd,d1,d2;
d=2*a+b;
d1=2*a;
d2=2*(a+b);
intx=x0,y=y0;
pDC->SetPixel(x,y,color);
while(x<x1)
{
if(d<0)
{
x++;
y++;
d+=d2;
}
else{
x++;
d+=d1;
}
pDC->SetPixel(x,y,color);
}
}
voidCDDALineView::BresenhamLine(CDC*pDC,intx0,inty0,intx1,inty1,COLORREFcolor)
{
intx,y,dx,dy;
dx=x1-x0;
dy=y1-y0;
floatk=dy/dx;
x=x0;
y=y0;
floate=-0.5;
for(inti=0;i<=dx;i++)
{
pDC->SetPixel(x,y,color);
x++;
e+=k;
if(e>=0)
{
y++;
e-=1;
}
}
}
仅供参考
❿ 根据两点画出直线,c++ windows编程 函数。帮忙实现
CDC类不是有现成的函数么?
CDC *pdc = CDC::FromHandle(hdc);
pdc->MoveTo(ps);
pdc->LineTo(pe);
以下是引用:
直线段的扫描转换算法
1 数值微分(DDA)法
我的理解就是以一个坐标轴为步长值(增量为1),另一个坐标根据直线的斜率(K)为
增量,然后四舍五入进行计算机,确定每一个点的坐标。
具体算法(我用OPENGL模拟)
void setPixel(GLint xCoord,GLint yCoord)
{
glBegin(GL_POINTS);
glVertex2i(xCoord,yCoord);
glEnd();
}
inline int round(const float a)
{
return int(a+0.5);
}
void lineDDA(int x0,int y0,int xEnd,int yEnd)
{
int dx = xEnd - x0,dy = yEnd - y0,steps,k;
float xIncrement,yIncrement,x = x0,y=y0;
if(abs(dx)>abs(dy))
{
steps = abs(dx);
}
else
{
steps = abs(dy);
}
xIncrement = float(dx)/float(steps);
yIncrement = float(dy)/float(steps);
setPixel(round(x),round(y));
for(k = 0;k<steps;k++)
{
x+=xIncrement;
y+=yIncrement;
setPixel(round(x),round(y));
}
}
2中点画线法
同样我理解的算法就是,以一个增量为多的坐标轴为步长值(为1),而另一个坐标
值是加1,还是不变取决于这两个坐标值中点是在这条直线的上方,还是下方。
具体算法如下:
void lineMiddle(int x0,int y0,int xEnd,int yEnd)
{
int a,b,c,d1,d2,d;
a = y0-yEnd;
b = xEnd-x0;
d = 2*a+b;//判别试(2a+b为初始值)
d1 = 2*a;//中点在直线下方增量值
d2 = 2*a+b;//中点在真线上方的增量值
int x,y;
x = x0;y=y0;
setPixel(x,y);
while(x<xEnd)
{
if(d<0)//中点在直线下方
{
x++;
y++;
d+=d2;
}
else//中点在直线上方
{
x++;
d+=d1;
}
setPixel(x,y);
}
}
3.Bresenham画线算法程序:
用一个坐标轴来当步长值(即+1),另一个坐标轴是否加1则跟据斜率(k)来确定,K
如果大于0.5,那么也加+1,如果小于0.5那么即不变。为了方便计算,如果d大于1
,那么就减一,归0。可设e,e=d-0.5,于是就有e>0时,加1,e<0时不变,这样便
于硬件实现。
算法实现如下:
void lineBresenham(int x0,int y0,int x1,int y1)
{
int x,y,dx,dy;
float k,e;
dx = x1 - x0;
dy = y1 - y0;;
k = (float)dy/dx;
e = -0.5;
x = x0;
y = y0;
setPixel(x,y);
for(int i =0;i<dx;i++)
{
x = x+1;
e = e+k;
if(e>=0)
{
y++;
e = e-1;
}
setPixel(x,y);
}
}