参考:https://www.bilibili.com/video/BV1FN4y157gX/?spm_id_from=333.788.recommend_more_video.-1&vd_source=5b4cd3f84aab3b0261aa6b6791252d89
0-45°之间直线的颜色插值
// 0 ≤ k ≤ 1
void BresenhaLine1(HDC hdc, CP2 p1, CP2 p2)
{
// 颜色插值
double byteRed0 = 0.0, byteGreen0 = 0.0, byteBlue0 = 1.0;
double byteRed1 = 0.0, byteGreen1 = 1.0, byteBlue1 = 0.0;
int dx = p2._x - p1._x;
int dy = p2._y - p1._y;
double incrRed = (byteRed1 - byteRed0) / dx;
double incrGreen = (byteGreen1 - byteGreen0) / dx;
double incrBlue = (byteBlue1 - byteBlue0) / dx;
int e = -dx;
double bRed = byteRed0, bGreen = byteGreen0, bBlue = byteGreen0;
for (int x = p1._x, y = p1._y; x < p2._x; x++)
{
SetPixel(hdc, x, y, RGB(bRed * 255, bGreen * 255, bBlue * 255));
bRed += incrRed;
bGreen += incrGreen;
bBlue += incrBlue;
e += (dy + dy);
if (e >= 0)
{
y++;
e -= (dx + dx);
}
}
}
中心线绘制直线 算法
void CenterLine(HDC hdc, CP2 p1, CP2 p2)
{
bool bInterChange = false;
int dx = fabs(p2._x - p1._x);
int dy = fabs(p2._y - p1._y);
int e, signX, signY, temp;
signX = (p2._x > p1._x) ? 1 : ((p2._x < p1._x) ? -1 : 0);
signY = (p2._y > p1._y) ? 1 : ((p2._y < p1._y) ? -1 : 0);
if (dy > dx)
{
temp = dx;
dx = dy;
dy = temp;
bInterChange = true;
}
e = dx - 2 * dy;
int x = p1._x, y = p1._y;
for (int i = 1; i < dx; i++)
{
SetPixel(hdc, x, y, RGB(0, 0, 255));
if (bInterChange)
{
y += signY;
}
else
{
x += signX;
}
if (e < 0)
{
if (bInterChange)
x += signX;
else
y += signY;
e += 2 * dx - 2 * dy;
}
else
{
e -= 2 * dy;
}
}
}
完成代码
// 05-中点画线算法
// 参考1 https://www.bilibili.com/video/BV1FN4y157gX/?spm_id_from=333.788.recommend_more_video.-1&vd_source=5b4cd3f84aab3b0261aa6b6791252d89
#ifndef UNICODE
#define UNICODE
#endif
#include <math.h>
#include <Windows.h>
#include <stdio.h>
#include <wchar.h>
#include <WinBase.h>
#define PI 3.1415926 // PI
#define ROUND(d) int(d+0.5) // 四舍五入
// 点
class CP2
{
public:
CP2()
:_x(0)
, _y(0)
{
}
CP2(double x, double y)
:_x(x)
, _y(y)
{
}
virtual ~CP2() {};
public:
double _x;
double _y;
};
// 0 ≤ k ≤ 1
void BresenhaLine1(HDC hdc, CP2 p1, CP2 p2)
{
// 颜色插值
double byteRed0 = 0.0, byteGreen0 = 0.0, byteBlue0 = 1.0;
double byteRed1 = 0.0, byteGreen1 = 1.0, byteBlue1 = 0.0;
int dx = p2._x - p1._x;
int dy = p2._y - p1._y;
double incrRed = (byteRed1 - byteRed0) / dx;
double incrGreen = (byteGreen1 - byteGreen0) / dx;
double incrBlue = (byteBlue1 - byteBlue0) / dx;
int e = -dx;
double bRed = byteRed0, bGreen = byteGreen0, bBlue = byteGreen0;
for (int x = p1._x, y = p1._y; x < p2._x; x++)
{
SetPixel(hdc, x, y, RGB(bRed * 255, bGreen * 255, bBlue * 255));
bRed += incrRed;
bGreen += incrGreen;
bBlue += incrBlue;
e += (dy + dy);
if (e >= 0)
{
y++;
e -= (dx + dx);
}
}
}
// 中心线 算法
void CenterLine(HDC hdc, CP2 p1, CP2 p2)
{
bool bInterChange = false;
int dx = fabs(p2._x - p1._x);
int dy = fabs(p2._y - p1._y);
int e, signX, signY, temp;
signX = (p2._x > p1._x) ? 1 : ((p2._x < p1._x) ? -1 : 0);
signY = (p2._y > p1._y) ? 1 : ((p2._y < p1._y) ? -1 : 0);
if (dy > dx)
{
temp = dx;
dx = dy;
dy = temp;
bInterChange = true;
}
e = dx - 2 * dy;
int x = p1._x, y = p1._y;
for (int i = 1; i < dx; i++)
{
SetPixel(hdc, x, y, RGB(0, 0, 255));
if (bInterChange)
{
y += signY;
}
else
{
x += signX;
}
if (e < 0)
{
if (bInterChange)
x += signX;
else
y += signY;
e += 2 * dx - 2 * dy;
}
else
{
e -= 2 * dy;
}
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rc;
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);
SetMapMode(hdc, MM_ANISOTROPIC);
SetWindowExtEx(hdc, rc.right, rc.bottom, NULL);
SetViewportExtEx(hdc, rc.right, -rc.bottom, NULL);
SetViewportOrgEx(hdc, rc.right / 2, rc.bottom / 2, NULL);
int r = 200;
// 1. 绘制一条直线
CenterLine(hdc, CP2(-300, 150), CP2(-300, -150));
// 2. 直线角间隔 10°
for (size_t i = 0; i < 360; i += 1)
{
double angle = i * PI / 180.0;
CenterLine(hdc, CP2(0, 0), CP2(ROUND(cos(angle) * r), ROUND(sin(angle) * r)));
}
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"05-中点画线算法";
WNDCLASS wc = { };
wc.style = CS_HREDRAW | CS_VREDRAW; // 重新绘制整个工作区
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"05-中点画线算法", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}