兩點直線演算法
❶ 直線掃描演算法(個人總結,僅供參考)
直線掃描演算法主要包含三種演算法,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);
}
}