Загрузка данных
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#define DX 60
#define DY 40
#define A_PARAM 2.4
typedef double (*MathFunc)(double);
static double g_xMin = -1.0;
static double g_xMax = 5.0;
static double g_yMin = -5.0;
static double g_yMax = 5.0;
static double g_mx = 1.0;
static double g_my = 1.0;
static int g_func = 0;
static BOOL g_running = TRUE;
static double g_vals[1001];
static double f1(double x)
{
if (x + 1.0 < 0.0 || fabs(x) < 1e-9) return NAN;
return sqrt(x + 1.0) - A_PARAM / x;
}
static double f2(double x)
{
double c = cos(x);
return c * c;
}
static MathFunc get_func(void) { return g_func == 0 ? f1 : f2; }
static int cmp_dbl(const void *a, const void *b)
{
double da = *(const double *)a, db = *(const double *)b;
return (da > db) - (da < db);
}
static void compute_scale(HWND hwnd, MathFunc fn)
{
RECT rc; GetClientRect(hwnd, &rc);
int W = rc.right, H = rc.bottom;
int N = 1000, cnt = 0;
double dx = (g_xMax - g_xMin) / N;
double x = g_xMin;
for (int i = 0; i <= N; i++, x += dx) {
double y = fn(x);
if (!isnan(y) && !isinf(y)) g_vals[cnt++] = y;
}
if (cnt < 2) { g_yMin = -1.0; g_yMax = 1.0; }
else {
qsort(g_vals, cnt, sizeof(double), cmp_dbl);
double lo = g_vals[(int)(cnt * 0.10)];
double hi = g_vals[(int)(cnt * 0.90)];
if (hi <= lo) { hi = lo + 1.0; lo -= 1.0; }
double pad = (hi - lo) * 0.10;
g_yMin = lo - pad;
g_yMax = hi + pad;
}
g_mx = (double)(W - 2 * DX) / (g_xMax - g_xMin);
g_my = (double)(H - 2 * DY) / (g_yMax - g_yMin);
}
static void Render(HWND hwnd, HDC hdc, MathFunc fn)
{
RECT rc; GetClientRect(hwnd, &rc);
int W = rc.right, H = rc.bottom;
HBRUSH hBg = CreateSolidBrush(RGB(255, 255, 255));
FillRect(hdc, &rc, hBg);
DeleteObject(hBg);
SetBkMode(hdc, TRANSPARENT);
compute_scale(hwnd, fn);
int osx = (g_yMin < 0.0 && g_yMax > 0.0)
? (int)(H - DY - g_my * (0.0 - g_yMin))
: (g_yMin >= 0.0 ? H - DY : DY);
int osy = (g_xMin < 0.0 && g_xMax > 0.0)
? (int)(DX + g_mx * (0.0 - g_xMin))
: (g_xMin >= 0.0 ? DX : W - DX);
HPEN pGrid = CreatePen(PS_DOT, 1, RGB(190, 190, 190));
HPEN pOld = (HPEN)SelectObject(hdc, pGrid);
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
SetTextColor(hdc, RGB(80, 80, 80));
char buf[32];
double stepX = (g_xMax - g_xMin) / 10.0;
double stepY = (g_yMax - g_yMin) / 10.0;
double xv = g_xMin;
for (int i = 0; i <= 10; i++, xv += stepX) {
int px = (int)(DX + g_mx * (xv - g_xMin));
MoveToEx(hdc, px, DY, NULL);
LineTo(hdc, px, H - DY);
sprintf(buf, "%.1f", xv);
int ty = osx + 8;
if (ty > H - 18) ty = H - 18;
if (ty < 4) ty = 4;
TextOutA(hdc, px - 14, ty, buf, (int)strlen(buf));
}
double yv = g_yMin;
for (int i = 0; i <= 10; i++, yv += stepY) {
int py = (int)(H - DY - g_my * (yv - g_yMin));
MoveToEx(hdc, DX, py, NULL);
LineTo(hdc, W - DX, py);
sprintf(buf, "%.2f", yv);
int tx = osy + 6;
if (tx > W - 55) tx = W - 55;
if (tx < 2) tx = 2;
TextOutA(hdc, tx, py - 8, buf, (int)strlen(buf));
}
SelectObject(hdc, pOld);
DeleteObject(pGrid);
HPEN pAxis = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
SelectObject(hdc, pAxis);
MoveToEx(hdc, DX, osx, NULL);
LineTo(hdc, W - DX, osx);
MoveToEx(hdc, W - DX, osx, NULL); LineTo(hdc, W - DX - 10, osx - 5);
MoveToEx(hdc, W - DX, osx, NULL); LineTo(hdc, W - DX - 10, osx + 5);
TextOutA(hdc, W - DX + 4, osx - 10, "X", 1);
MoveToEx(hdc, osy, H - DY, NULL);
LineTo(hdc, osy, DY);
MoveToEx(hdc, osy, DY, NULL); LineTo(hdc, osy - 5, DY + 10);
MoveToEx(hdc, osy, DY, NULL); LineTo(hdc, osy + 5, DY + 10);
TextOutA(hdc, osy + 6, DY - 16, "Y", 1);
SelectObject(hdc, pOld);
DeleteObject(pAxis);
HRGN hClipRgn = CreateRectRgn(DX, DY, W - DX, H - DY);
SelectClipRgn(hdc, hClipRgn);
COLORREF col = (g_func == 0) ? RGB(0, 90, 200) : RGB(200, 0, 60);
HPEN pCurve = CreatePen(PS_SOLID, 2, col);
SelectObject(hdc, pCurve);
int N = (W - 2 * DX) * 3;
if (N < 1500) N = 1500;
int first = 1;
double prev_py = 0.0;
double dx = (g_xMax - g_xMin) / (double)N;
double x = g_xMin;
for (int i = 0; i <= N; i++, x += dx) {
double y = fn(x);
if (isnan(y) || isinf(y)) { first = 1; continue; }
int px = (int)(DX + g_mx * (x - g_xMin));
int py = (int)(H - DY - g_my * (y - g_yMin));
if (!first && fabs((double)py - prev_py) > H * 0.75) { first = 1; }
if (first) { MoveToEx(hdc, px, py, NULL); first = 0; }
else LineTo(hdc, px, py);
prev_py = (double)py;
}
SelectObject(hdc, pOld);
DeleteObject(pCurve);
SelectClipRgn(hdc, NULL);
DeleteObject(hClipRgn);
SetTextColor(hdc, col);
const char *fname = (g_func == 0)
? "f1(x) = sqrt(x+1) - 2.4/x"
: "f2(x) = cos^2(x)";
TextOutA(hdc, DX + 4, DY + 4, fname, (int)strlen(fname));
SetTextColor(hdc, RGB(100, 100, 100));
const char *hint = "+/- : masshtab Left/Right : sdvig Tab : smena funkcii Esc : vyhod";
TextOutA(hdc, DX, H - DY + 10, hint, (int)strlen(hint));
char info[64];
sprintf(info, "X: [%.2f, %.2f]", g_xMin, g_xMax);
SetTextColor(hdc, RGB(60, 60, 60));
TextOutA(hdc, W - 180, DY + 4, info, (int)strlen(info));
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_KEYDOWN: {
switch (wp) {
case VK_LEFT: {
double w = g_xMax - g_xMin;
g_xMin -= 1.0;
if (g_func == 0 && g_xMin < -1.0) {
g_xMin = -1.0;
}
g_xMax = g_xMin + w;
break;
}
case VK_RIGHT: {
double w = g_xMax - g_xMin;
g_xMin += 1.0;
g_xMax = g_xMin + w;
break;
}
case VK_ADD: case VK_OEM_PLUS:
if (g_xMax - g_xMin > 1.0) {
g_xMin += 0.5;
g_xMax -= 0.5;
}
break;
case VK_SUBTRACT: case VK_OEM_MINUS:
g_xMin -= 0.5;
if (g_func == 0 && g_xMin < -1.0) {
g_xMin = -1.0;
}
g_xMax += 0.5;
break;
case VK_TAB: {
g_func = 1 - g_func;
if (g_func == 0 && g_xMin < -1.0) {
g_xMin = -1.0;
g_xMax = 5.0;
}
break;
}
case VK_ESCAPE: DestroyWindow(hwnd); return 0;
}
InvalidateRect(hwnd, NULL, TRUE);
break;
}
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
Render(hwnd, hdc, get_func());
EndPaint(hwnd, &ps);
break;
}
case WM_SIZE:
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
g_running = FALSE;
break;
default:
return DefWindowProcW(hwnd, msg, wp, lp);
}
return 0;
}
int main(void)
{
printf("=== Lab. rabota No8. Variant 16 ===\n");
printf(" f1(x) = sqrt(x+1) - %.1f/x\n", A_PARAM);
printf(" f2(x) = cos^2(x)\n\n");
while (1) {
printf("Vvedite nachalo intervala po osi X (ne menshe -1): ");
if (scanf("%lf", &g_xMin) != 1) { printf("Oshibka vvoda.\n"); return 1; }
if (g_xMin < -1.0) { printf("Oshibka: nachalo ne mozhet byt menshe -1!\n"); continue; }
printf("Vvedite konec intervala po osi X: ");
if (scanf("%lf", &g_xMax) != 1) { printf("Oshibka vvoda.\n"); return 1; }
if (g_xMin < g_xMax) break;
printf("Oshibka: nachalo dolzhno byt menshe konca!\n");
}
printf("\n+/-: masshtab | Left/Right: sdvig | Tab: smena func | Esc: vyhod\n\n");
HINSTANCE hInst = GetModuleHandleW(NULL);
WNDCLASSW wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInst;
wc.lpszClassName = L"Lab8Graph";
wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassW(&wc);
HWND hwnd = CreateWindowExW(
0, L"Lab8Graph",
L"Lab. rabota No8 - Postroenie grafikov (Variant 16)",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL, NULL, hInst, NULL
);
if (!hwnd) return 1;
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
UpdateWindow(hwnd);
MSG msg;
while (g_running && GetMessageW(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}