用VC++编一个曲线拟合程序

用VC++编一个曲线拟合程序,第1张

在windows环境下编程序,最传统的方法是Win32 API,历史极其悠久,核心内容自从windows诞生至今几乎没变化。他很庞大,包括界面部分(即GDI),还有消息处理部分(要让鼠标拖动就要使用鼠标消息),还有文件,打印,网络等等功能,他作为Windows最直接的编程方法,至今都很重要。Win32 API是使用C语言的,为了发挥C++的优势,微软基于Win32 API,开发了MFC,他就是Visual C++的主要功能之一。我比较懒,也不高兴学MFC,毕竟做的程序简单,体现不出MFC的优势,如果程序中控件(例如按钮,文本)比较多,窗口较多,那么用MFC就方便很多。

楼主要求的程序,不是很复杂,用纯粹的C语言,使用Win32API,就可以了,楼主要学的话看一下WIN32 API的书,当然你也可以学MFC,前提要对C++比较熟悉,类,继承,多态一定要搞清楚。

我写了一下,代码如下:

#include <windows.h>

#include <math.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM)

int cxClient, cyClient ,cByteWidth

POINT apt[5]

bool requestRedraw

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{

//入口点,就是main函数

static TCHAR szAppName[] = TEXT ("Bezier")

HWND hwnd

MSG msg

WNDCLASS wndclass

wndclass.style = CS_HREDRAW | CS_VREDRAW

wndclass.lpfnWndProc = WndProc

wndclass.cbClsExtra= 0

wndclass.cbWndExtra= 0

wndclass.hInstance = hInstance

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION)

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW)

wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH)

wndclass.lpszMenuName = NULL

wndclass.lpszClassName = szAppName

if (!RegisterClass (&wndclass))

{

MessageBox (NULL, TEXT ("Program requires Windows NT!"),

szAppName, MB_ICONERROR)

return 0

}

//创建一个窗口

hwnd = CreateWindow (szAppName, TEXT ("Bezier Splines"),

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL)

ShowWindow (hwnd, iCmdShow)

UpdateWindow (hwnd)

//建立消息循环,来接受鼠标动作,窗口缩放,移动等动作

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg)

DispatchMessage (&msg)

}

return msg.wParam

}

void DrawBezier (HDC hdc,HDC hdcMem)

{

//这里是画曲线,通过打点的方式画到位图中,然后显示,当然算法有待改进

static char bits [259200]

if(requestRedraw)

{

memset(bits,0xFF,259200)

float tDelat = 0.025/max(cxClient,cyClient)

for(float t = 0 t <1 + tDelat t += tDelat)

{

float mt = 1 - t

float t2 = t * t,t3 = t2 * t,t4 = t3 * t

float mt2 = mt * mt,mt3 = mt2 * mt,mt4 = mt3 * mt

int fX = apt[0].x * t4 + 4 * apt[1].x * t3 * mt + 6 * apt[2].x * t2 * mt2

+ 4 * apt[3].x * t * mt3 + apt[4].x * mt4 + 0.5f

int fY = apt[0].y * t4 + 4 * apt[1].y * t3 * mt + 6 * apt[2].y * t2 * mt2

+ 4 * apt[3].y * t * mt3 + apt[4].y * mt4 + 0.5f

bits[( fX + ((fY * cByteWidth) <<3)) >>3] &= (0xFF ^ ( 0x80 >>( fX &0x07 )))

}

requestRedraw = false

}

HBITMAP hBitmap

BITMAP bitmap = { 0, cxClient, cyClient, cByteWidth, 1, 1 }

bitmap.bmBits = bits

hBitmap = CreateBitmapIndirect (&bitmap)

SelectObject(hdcMem,hBitmap)

BitBlt (hdc, 0, 0, cxClient, cyClient,

hdcMem, 0, 0, SRCCOPY)

DeleteObject(hBitmap)

//把点用直线连起来

static HPEN hRedPen = CreatePen (PS_SOLID, 1, RGB (255, 0, 0))

SelectObject(hdc,hRedPen)

MoveToEx (hdc, apt[0].x, apt[0].y, NULL)

LineTo (hdc, apt[1].x, apt[1].y)

LineTo (hdc, apt[2].x, apt[2].y)

LineTo (hdc, apt[3].x, apt[3].y)

LineTo (hdc, apt[4].x, apt[4].y)

}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

//消息循环处理函数

static HDC hdc,hdcMem

static PAINTSTRUCT ps

static int chosen = -1,minDistance = 1e3

switch (message)

{

case WM_CREATE:

hdc = GetDC (hwnd)

hdcMem = CreateCompatibleDC (hdc)

ReleaseDC(hwnd,hdc)

return 0

//当窗口大小改变,要重新画曲线

case WM_SIZE:

cxClient = LOWORD (lParam)

cyClient = HIWORD (lParam)

cByteWidth = int(ceil(cxClient / 8.0f))%2 == 0 ? ceil(cxClient / 8.0f) : ceil(cxClient / 8.0f)+1

apt[0].x = 1 * cxClient / 6 apt[0].y = 1 * cyClient / 2

apt[1].x = 1 * cxClient / 2 apt[1].y = 1 * cyClient / 6

apt[2].x = 1 * cxClient / 2 apt[2].y = 4 * cyClient / 5

apt[3].x = 2 * cxClient / 3 apt[3].y = 4 * cyClient / 5

apt[4].x = 4 * cxClient / 5 apt[4].y = 1 * cyClient / 3

chosen = -1

requestRedraw = true

return 0

//鼠标点击,计算出选择哪一个要移动的点

case WM_LBUTTONDOWN:

minDistance = 1e3chosen = -1

for(int i = 0 i <5 i++ )

{

int dx = LOWORD (lParam) - apt[i].x int dy = HIWORD (lParam) - apt[i].y

int currentDist = dx*dx + dy*dy

if(currentDist <minDistance)

{

minDistance = currentDist

chosen = i

}

}

return 0

//鼠标移动,让点跟随鼠标

case WM_MOUSEMOVE:

if (wParam &MK_LBUTTON &&chosen >= 0)

{

apt[chosen].x = LOWORD (lParam)

apt[chosen].y = HIWORD (lParam)

requestRedraw = true

PostMessage(hwnd,WM_PAINT,NULL,NULL)

}

return 0

//这个是windows传给程序的绘图命令

case WM_PAINT:

InvalidateRect (hwnd, NULL, FALSE)

hdc = BeginPaint (hwnd, &ps)

DrawBezier (hdc,hdcMem)

EndPaint (hwnd, &ps)

return 0

case WM_DESTROY:

PostQuitMessage (0)

return 0

}

return DefWindowProc (hwnd, message, wParam, lParam)

}

不懂的话,可以Hi我

三次样条插值程序

float hypot(float X, float Y)

void tspLine(int n, int ch, int *Num, float x[], float y[], float u1[], float v1[], float tx1 = 0.0, float tx2 = 0.0, float ty1 = 0.0, float ty2 = 0.0)

float hypot(float X, float Y)

{

return sqrt(X * X + Y * Y)

}

void tspLine(int n, int ch, int *Num, float x[], float y[], float u1[], float v1[], float tx1, float tx2, float ty1, float ty2)

{

int i, j, iNum

float *a, *b, *c, *dx, *dy

float *qx, *qy

float *t, *px, *py

float tt, bx3, bx4, by3, by4

float cx, cy

float u[3]

a = new float[n + 1]

b = new float[n + 1]

c = new float[n + 1]

dx = new float[n + 1]

dy = new float[n + 1]

qx = new float[n + 1]

qy = new float[n + 1]

t = new float[n + 1]

px = new float[n + 1]

py = new float[n + 1]

iNum = 0

for (i = 1i <= ni++)

t[i] = hypot(x[i] - x[i - 1], y[i] - y[i - 1])

switch (ch)

{

case 0: //抛物条件

u[0] = (x[1] - x[0]) / t[1]

u[1] = (x[2] - x[1]) / t[2]

u[2] = (u[1] - u[0]) / (t[2] + t[1])

tx1 = u[0] - u[2] * t[1]

u[0] = (y[1] - y[0]) / t[1]

u[1] = (y[2] - y[1]) / t[2]

u[2] = (u[1] - u[0]) / (t[2] + t[1])

ty1 = u[0] - u[2] * t[1]

u[0] = (x[n] - x[n - 1]) / t[n]

u[1] = (x[n - 1] - x[n - 2]) / t[n - 1]

u[2] = (u[0] - u[1]) / (t[n] + t[n - 1])

tx2 = u[0] + u[2] * t[n]

u[0] = (y[n] - y[n - 1]) / t[n]

u[1] = (y[n - 1] - y[n - 2]) / t[n - 1]

u[2] = (u[0] - u[1]) / (t[n] + t[n - 1])

ty2 = u[0] + u[2] * t[n]

break

case 1: //夹持条件

a[0] = 1.0

c[0] = 0.0

dx[0] = tx1

dy[0] = ty1

a[n] = 1.0

b[n] = 0.0

dx[n] = tx2

dy[n] = ty2

break

case 2: //自由条件

a[0] = 2.0

c[0] = 1.0

dx[0] = 3.0 * (x[1] - x[0]) / t[1]

dy[0] = 3.0 * (y[1] - y[0]) / t[1]

a[n] = 2.0

b[n] = 1.0

dx[n] = 3.0 * (x[n] - x[n - 1]) / t[n]

dy[n] = 3.0 * (y[n] - y[n - 1]) / t[n]

break

case 3: //循环条件

a[0] = 2.0

c[0] = 1.0

dx[0] = 3.0 * (x[1] - x[0]) / t[1] - (t[1] * (x[2] - x[1]) / t[2] - x[1] + x[0]) / (t[1] + t[2])

dy[0] = 3.0 * (y[1] - y[0]) / t[1] - (t[1] * (y[2] - y[1]) / t[2] - y[1] + y[0]) / (t[1] + t[2])

a[n] = 2.0

b[n] = 1.0

dx[n] = 3.0 * (x[n] - x[n - 1]) / t[n]

dx[n] = dx[n] + (x[n] - x[n - 1] - t[n] * (x[n - 1] - x[n - 2]) / t[n - 1]) / (t[n] + t[n - 1])

dy[n] = 3.0 * (y[n] - y[n - 1]) / t[n]

dy[n] = dy[n] + (y[n] - y[n - 1] - t[n] * (y[n - 1] - y[n - 2]) / t[n - 1]) / (t[n] + t[n - 1])

}

//计算方程组系数阵和常数阵

for (i = 1i <ni++)

{

j = i + 1

a[i] = 2.0 * (t[i] + t[j])

b[i] = t[j]

c[i] = t[i]

dx[i] = 3.0 * (t[i] * (x[j] - x[i]) / t[j] + t[j] * (x[i] - x[i - 1]) / t[i])

dy[i] = 3.0 * (t[i] * (y[j] - y[i]) / t[j] + t[j] * (y[i] - y[i - 1]) / t[i])

}

//采用追赶法解方程组

c[0] = c[0] / a[0]

for (i = 1i <ni++)

{

a[i] -= b[i] * c[i - 1]

c[i] /= a[i]

}

a[n] -= b[n] * c[i - 1]

qx[0] = dx[0] / a[0]

qy[0] = dy[0] / a[0]

for (i = 1i <= ni++)

{

qx[i] = (dx[i] - b[i] * qx[i - 1]) / a[i]

qy[i] = (dy[i] - b[i] * qy[i - 1]) / a[i]

}

px[n] = qx[n]

py[n] = qy[n]

for (i = n - 1i >= 0i--)

{

px[i] = qx[i] - c[i] * px[i + 1]

py[i] = qy[i] - c[i] * py[i + 1]

}

//计算曲线上点的坐标

for (i = 0i <ni++)

{

j = i + 1

bx3 = (3.0 * (x[j] - x[i]) / t[j] - 2.0 * px[i] - px[j]) / t[j]

bx4 = ((2.0 * (x[i] - x[j]) / t[j] + px[i] + px[j]) / t[j]) / t[j]

by3 = (3.0 * (y[j] - y[i]) / t[j] - 2.0 * py[i] - py[j]) / t[j]

by4 = ((2.0 * (y[i] - y[j]) / t[j] + py[i] + py[j]) / t[j]) / t[j]

tt = 0.0

while (tt <= t[j])

{

cx = x[i] + (px[i] + (bx3 + bx4 * tt) * tt) * tt

cy = y[i] + (py[i] + (by3 + by4 * tt) * tt) * tt

u1[iNum] = cx

v1[iNum] = cy

iNum++

tt += 0.5

}

u1[iNum] = x[j]

v1[iNum] = y[j]

iNum++

}

delete a

delete b

delete c

delete dx

delete dy

delete qx

delete qy

delete t

delete px

delete py

*Num = iNum

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12075817.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存