Ⅰ 日本畫線演算法 原理
這不是新的演算法,它和我們的乘法豎式其實是一樣的。
算交點數就能得出乘法的結果,這不奇怪,
從最簡單的乘法看,比如1x3=3,
你在橫向劃一條線,縱向劃三條線,交點數當然是3個。
Ⅱ 用C++如何實現bresenham畫線演算法計算機圖形學上面有個drawpixel的函數。不知道怎麼用。
drawpixel()函數這就是VC畫點的,不同的平台由不同的函數來畫點,這個是API函數不管什麼平台歸結到底都是調用這個函數來畫點。
COLORREF SetPixel(
HDC hdc, // handle to DC
int X, // x-coordinate of pixel
int Y, // y-coordinate of pixel
COLORREF crColor // pixel color
);
Ⅲ Bresenham畫線演算法決策變數的初值
書上?什麼書?
Ⅳ bresenham畫線演算法與計算機圖形學畫線演算法有什麼不同
計算機圖形學畫線演算法很多,有DDA演算法、逐點比較法、Bresenham演算法等,Bresenham演算法是最著名的,而且演算法中只用到了加法和移位運算,沒有浮點數,沒有乘除法,所以執行速度最快。
Ⅳ 利用C語言編寫 能夠畫出任意斜率的直線演算法程序(利用中點畫線法改編)
將DDA演算法改成中點劃線演算法即可
// DDA畫線View.cpp : implementation of the CDDAView class
//
#include "stdafx.h"
#include "DDA畫線.h"
#include "DDA畫線Doc.h"
#include "DDA畫線View.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDDAView
IMPLEMENT_DYNCREATE(CDDAView, CView)
BEGIN_MESSAGE_MAP(CDDAView, CView)
//{{AFX_MSG_MAP(CDDAView)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDDAView construction/destruction
CDDAView::CDDAView()
{
// TODO: add construction code here
}
CDDAView::~CDDAView()
{
}
BOOL CDDAView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CDDAView drawing
void CDDAView::OnDraw(CDC* pDC)
{
CDDADoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
int xx,yy,x2,y2,m,n;
float dx,dy,k,x,y;
int x0=50,y0=500,x1=50,y1=50;
if(x0>x1)
{
m=x0;x0=x1;x1=m;
m=y0;y0=y1;y1=m;
}
dx=x1-x0;
dy=y1-y0;
k=dy/dx;
if(x0==x1)
{
if(y0>y1)
{
n=y0;
y0=y1;
y1=n;
}
for(y2=y0;y2<=y1;)
{
for(n=-10;n<11;)
{
pDC->SetPixel(x0+n,y2,255);
n++;
}
y2=y2+3;
}
}
if(k>=-1&&k<=1.0)
{
y=y0;
for(x2=x0;x2<=x1;)
{
yy=(int)(y+0.5);
for(n=-10;n<11;)
{
pDC->SetPixel(x2,yy+n,255);
n++;
}
y=y+k;
x2++;
}
}
else if(k>1)
{
x=x0;
k=dx/dy;
for(y2=y0;y2<=y1;)
{
xx=(int)(x+0.5);
for(n=-10;n<11;)
{
pDC->SetPixel(xx+n,y2,255);
n++;
}
x=x+k;
y2++;
}
}
else if(k<-1)
{
x=x1;
k=dx/dy;
for(y2=y1;y2<=y0;)
{
xx=(int)(x+0.5);
for(n=-10;n<11;)
{
pDC->SetPixel(xx+n,y2,255);
n++;
}
x=x+k;
y2++;
}
}
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CDDAView printing
BOOL CDDAView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CDDAView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CDDAView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CDDAView diagnostics
#ifdef _DEBUG
void CDDAView::AssertValid() const
{
CView::AssertValid();
}
void CDDAView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CDDADoc* CDDAView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDDADoc)));
return (CDDADoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDDAView message handlers
Ⅵ Bresenham畫線演算法
基本上Bresenham畫線演算法的思路如下:
//
假設該線段位於第一象限內且斜率大於0小於1,設起點為(x1,y1),終點為(x2,y2).
//
根據對稱性,可推導至全象限內的線段.
1.畫起點(x1,y1).
2.准備畫下個點。x坐標增1,判斷如果達到終點,則完成。否則,由圖中可知,下個要畫的點要麼為當前點的右鄰接點,要麼是當前點的右上鄰接點.
2.1.如果線段ax+by+c=0與x=x1+1的交點的y坐標大於M點的y坐標的話,下個點為U(x1+1,y1+1)
2.2.否則,下個點為B(x1+1,y1+1)
3.畫點(U或者B).
4.跳回第2步.
5.結束.
這里需要細化的是怎麼判斷下個要畫的點為當前點的右鄰接點還是當前點的右上鄰接點.
設線段方程:ax+by+c=0(x1<x<x2,y1<y<y2)
令dx=x2-x1,dy=y2-y1
則:斜率-a/b
=
dy/dx.
從第一個點開始,我們有F(x,1,y1)
=
a*x1+b*y1+c=0
下面求線段ax+by+c=0與x=x1+1的交點:
由a*(x1+1)+b*y+c
=
0,
求出交點坐標y=(-c-a(x1+1))/b
所以交點與M的y坐標差值Sub1
=
(-c-a(x1+1))/b
-
(y1+0.5)
=
-a/b-0.5,即Sub1的處始值為-a/b-0.5。
則可得條件當
Sub1
=
-a/b-0.5>0時候,即下個點為U.
反之,下個點為B.
代入a/b,則Sub1
=
dy/dx-0.5.
因為是個循環中都要判斷Sub,所以得求出循環下的Sub表達式,我們可以求出Sub的差值的表達式.下面求x=x1+2時的Sub,即Sub2
1.如果下下個點是下個點的右上鄰接點,則
Sub2
=
(-c-a(x1+2))/b
-
(y1+1.5)
=
-2a/b
-
1.5
故Sub差值Dsub
=
Sub2
-
Sub1
=
-2a/b
-
1.5
-
(-a/b-0.5)
=
-a/b
-
1.代入a/b得Dsub
=
dy/dx
-1;
2.如果下下個點是下個點的右鄰接點,
Sub2
=
(-c-a(x1+2))/b
-
(y1+0.5)
=
-2a/b
-
0.5
故Sub差值Dsub
=
Sub2
-
Sub1
=
-2a/b
-
0.5
-
(-a/b-0.5)
=
-a/b.
代入a/b得Dsub
=
dy/dx;
於是,我們有了Sub的處始值Sub1
=
-a/b-0.5
=
dy/dx-0.5,又有了Sub的差值的表達式Dsub
=
dy/dx
-1
(當Sub1
>
0)或
dy/dx(當Sub1
<
0).細化工作完成。
於是pcode可以細化如下:
//
Pcode
for
Bresenham
Line
//
By
SoRoMan
x=x1;
y=y1;
dx
=
x2-x1;
dy
=
y2-y1;
Sub
=
dy/dx-0.5;
//
賦初值,下個要畫的點與中點的差值
DrawPixel(x,
y);
//
畫起點
while(x<x2)
{
x++;
if(Sub
>
0)
//
下個要畫的點為當前點的右上鄰接點
{
Sub
+=
dy/dx
-
1;
//下下個要畫的點與中點的差值
y++;
//
右上鄰接點y需增1
}
else//
下個要畫的點為當前點的右鄰接點
{
Sub
+=
dy/dx;
}
//
畫下個點
DrawPixel(x,y);
}
PS:一般優化:
為避免小數轉整數以及除法運算,由於Sub只是用來進行正負判斷,所以可以令Sub
=
2*dx*Sub
=
2dy-dx,則
相應的DSub
=
2dy
-
2dx或2dy.
思考1:如果Sub
=
0時,會產生取兩個點都可以的問題。這個問題還沒深入。
Ⅶ bresenham畫線演算法
用MFC還要bresenham幹嘛
Ⅷ 劃線演算法 原理
1.這不是新的演算法,它和我們的乘法豎式其實是一樣的
2.算交點數就能得出乘法的結果,這不奇怪,
從最簡單的乘法看,比如1x3=3
你在橫向劃一條線,縱向劃三條線,交點數當然是3個
再比如2x3=6
你在橫向劃兩條線,縱向劃三條線,交點數當然是6個,不信,你可以數。
原因是:橫向一條線,與縱向三條線,交點數是3個;
而現在,橫向有兩條線,所以交點數有2x3個,也就是6個
這是一位數的乘法,已經清楚了。
但對於多位數的呢,也可以用和上面一樣的方法,橫向劃一組線,縱向劃一組線,然後數交點數,對於比較大的數,恐怕大家沒耐心把點數完。
3.對於多位數的乘法,用視頻中的劃線法,其實和我們的乘法豎式其實是一樣的。
視頻的例子:21x13=273
乘法豎式:
21
x13
----
63
21
----
273
我們在視屏中,看到有數出:2,1,6,3這么些點數,並且把6和1相加變成7放到了結果中。
而在以上乘法豎式中,也有2,1,6,3這么些數字,並且也是把6和1相加變成7放到了結果中。
視頻的例子:123x321=39483
乘法豎式:
123
x321
-------
123
246
369
-------
39483
我們在視屏中,看到有把點數:1,4,9相加得出14,而14中的這個1被進到前面一位去了;
而在以上乘法豎式中,也有把數字:1,4,9相加得出14,而14中的這個1被進到前面一位去。
Ⅸ 求長方形之間的畫線演算法
長方形之間的畫線是怎麼畫的?都不明白樓主想畫什麼線.