Запустив программу, вы видите на экране график функции z = x / y. Вы можете изменить масштаб графика, нажимая +/-. Вы можете изменить угол зрения. Для этого сначала нажмите <NumLock>, после чего включится дополнительная цифровая клавиатура. Нажимая стрелки, вы измените угол зрения. Нажав <5>, вы вернётесь к исходной точке и масштабу. Сделано под Windows 98 на Visual C++ 6.0. Скачать программу, код, инструкцию: https://yadi.sk/d/bXK0rNYX6NZ4LQ
// p3View.cpp : implementation of the CP3View class //
double xa, ya, za; // вектор ориентации в пространстве осей системы координат ("определяющий вектор") - смотрит на наблюдателя (ось Oz) double xb, yb, zb; // ось Ox в 3D double xc, yc, zc; // ось Oy в 3D
int scale; // масштаб графика int flag; // флаг рисования отрезка в 3D: 0 - не рисовать; 1 - первая точка отрезка; 2 - вторая точка отрезка int number; // номер графика int aa;
void initialize (); // инициализация исходных данных перед построением графика void calculate (); // расчёт векторов осей Oz, Ox, Oy void draw (CDC *); // рисование графика void line (double, double, double, double, double, double, CDC *); // рисование линии в 3D
double f1 (double, double); // функция z = f (x, y), график которой строится
e = 0; for (a = -500; a <= 500; a += 30) // проходим значения x { flag = 0; for (b = -500; b <= 500; b++) // проходим значения y { switch (number) // выбираем, график какой функции строится { case 1: d = f1 ((double) a / scale, (double) b / scale) * scale; break; default: d = 0; }
// Если имеются две рассчитанные точки, строим линию в 3D if (flag == 2) line (a, b - 1, e, a, b, d, pDC); e = d; } }
for (b = -500; b <= 500; b += 30) // проходим значения y { flag = 0; for (a = -500; a <= 500; a++) // проходим значения x { switch (number) // выбираем, график какой функции строится { case 1: d = f1 ((double) a / scale, (double) b / scale) * scale; break; default: d = 0; }
// Если имеются две рассчитанные точки, строим линию в 3D if (flag == 2) line (a - 1, b, e, a, b, d, pDC); e = d; } } }
void line (double a, double b, double c, double d, double e, double f, CDC *pDC) { double g, h; // первая точка на плоскости double i, j; // вторая точка на плоскости
g = a * xb + b * yb + c * zb; h = a * xc + b * yc + c * zc; // проекция первого вектора на ось Oy i = d * xb + e * yb + f * zb; j = d * xc + e * yc + f * zc; // проекция второго вектора на ось Oy
if (g > 1500) g = 1500; if (g < -1500) g = -1500; if (i > 1500) i = 1500; if (i < -1500) i = -1500;
Группа для программистов ( programming )
:Юрий Казекин
Построение 3D-графика функции
Запустив программу, вы видите на экране график функции z = x / y.
Вы можете изменить масштаб графика, нажимая +/-.
Вы можете изменить угол зрения. Для этого сначала нажмите <NumLock>, после чего включится дополнительная цифровая клавиатура. Нажимая стрелки, вы измените угол зрения. Нажав <5>, вы вернётесь к исходной точке и масштабу.
Сделано под Windows 98 на Visual C++ 6.0.
Скачать программу, код, инструкцию: https://yadi.sk/d/bXK0rNYX6NZ4LQ
//
#include "stdafx.h"
#include <math.h>
#include "p3.h"
#include "p3Doc.h"
#include "p3View.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Данные задачи
double xa, ya, za; // вектор ориентации в пространстве осей системы координат ("определяющий вектор") - смотрит на наблюдателя (ось Oz)
double xb, yb, zb; // ось Ox в 3D
double xc, yc, zc; // ось Oy в 3D
int scale; // масштаб графика
int flag; // флаг рисования отрезка в 3D: 0 - не рисовать; 1 - первая точка отрезка; 2 - вторая точка отрезка
int number; // номер графика
int aa;
void initialize (); // инициализация исходных данных перед построением графика
void calculate (); // расчёт векторов осей Oz, Ox, Oy
void draw (CDC *); // рисование графика
void line (double, double, double, double, double, double, CDC *); // рисование линии в 3D
double f1 (double, double); // функция z = f (x, y), график которой строится
/////////////////////////////////////////////////////////////////////////////
// CP3View
IMPLEMENT_DYNCREATE(CP3View, CView)
BEGIN_MESSAGE_MAP(CP3View, CView)
//{{AFX_MSG_MAP(CP3View)
ON_WM_CHAR()
//}}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()
/////////////////////////////////////////////////////////////////////////////
// CP3View construction/destruction
CP3View::CP3View()
{
number = 1; // номер графика функции
aa = 0;
initialize ();
}
CP3View::~CP3View()
{
}
BOOL CP3View::PreCreateWindow(CREATESTRUCT& cs)
{
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CP3View drawing
void CP3View::OnDraw (CDC *pDC)
{
CP3Doc *pdoc = GetDocument ();
ASSERT_VALID (pdoc);
CString a;
calculate ();
draw (pDC); // рисование 3D-графика
// рисование осей координат в 3D
line (500, 0, 0, -500, 0, 0, pDC);
line (0, 500, 0, 0, -500, 0, pDC);
line (0, 0, 0, 0, 0, 500, pDC);
a.Format ("key = %i.", aa);
pDC -> TextOut (10, 10, a);
}
/////////////////////////////////////////////////////////////////////////////
// CP3View printing
BOOL CP3View::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CP3View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}
void CP3View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}
/////////////////////////////////////////////////////////////////////////////
// CP3View diagnostics
#ifdef _DEBUG
void CP3View::AssertValid() const
{
CView::AssertValid();
}
void CP3View::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CP3Doc* CP3View::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CP3Doc)));
return (CP3Doc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CP3View message handlers
void CP3View::OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
{
double a, b; // временные переменные
switch (nChar)
{
case '5': // возврат к значениям по умолчанию
initialize ();
break;
case 'a': // график первой функции
number = 1;
break;
case '4': // смещение графика влево <Left arrow>
a = xa * cos (.1) + ya * sin (.1);
b = -xa * sin (.1) + ya * cos (.1);
xa = a;
ya = b;
break;
case '6': // смещение графика вправо <Right arrow>
a = xa * cos (.1) - ya * sin (.1);
b = xa * sin (.1) + ya * cos (.1);
xa = a;
ya = b;
break;
case '8': // смещение графика вверх <Up arrow>
xa -= xb * sin (.1);
ya -= yb * sin (.1);
za -= zb * sin (.1);
break;
case '2': // смещение графика вниз <Down arrow>
xa += xb * sin (.1);
ya += yb * sin (.1);
za += zb * sin (.1);
break;
case '+': // увеличение масштаба
scale = (int) (scale * 1.3);
break;
case '-': // уменьшение масштаба
scale = (int) (scale / 1.3);
if (scale == 0) scale = 1;
}
CView::OnChar (nChar, nRepCnt, nFlags);
aa = nChar;
Invalidate ();
}
void initialize ()
{
xa = ya = za = 1; // определяющий вектор
xc = yc = zc = 0; // вектор направления оси Oy
scale = 50; // масштаб
}
void calculate ()
{
double a, b, c; // вспомогательные переменные
// 1. Нормирование определяющего вектора
a = sqrt (xa * xa + ya * ya + za * za);
xa /= a;
ya /= a;
za /= a;
// 2. Проекция вектора (0, 0, 1) на определяющий вектор
a = xa * za;
b = ya * za;
c = za * za;
xb = -a;
yb = -b;
zb = 1 - c;
// 3. Нормирование вектора оси Ox
a = sqrt (xb * xb + yb * yb + zb * zb);
if (a == 0) return;
xb /= a;
yb /= a;
zb /= a;
// 4. Вычисление вектора оси Oy; векторное произведение двух других осей.
a = ya * zb - za * yb;
b = za * xb - xa * zb;
c = xa * yb - ya * xb;
// 5. Инверсия левой тройки векторов
if (a * xc + b * yc + c * zc < 0)
{
xb = -xb; yb = -yb; zb = -zb;
xc = -a; yc = -b; zc = -c;
}
else {xc = a; yc = b; zc = c;}
}
void draw (CDC *pDC)
{
int a, b;
double d, e;
e = 0;
for (a = -500; a <= 500; a += 30) // проходим значения x
{
flag = 0;
for (b = -500; b <= 500; b++) // проходим значения y
{
switch (number) // выбираем, график какой функции строится
{
case 1:
d = f1 ((double) a / scale, (double) b / scale) * scale;
break;
default:
d = 0;
}
// Если имеются две рассчитанные точки, строим линию в 3D
if (flag == 2) line (a, b - 1, e, a, b, d, pDC);
e = d;
}
}
for (b = -500; b <= 500; b += 30) // проходим значения y
{
flag = 0;
for (a = -500; a <= 500; a++) // проходим значения x
{
switch (number) // выбираем, график какой функции строится
{
case 1:
d = f1 ((double) a / scale, (double) b / scale) * scale;
break;
default:
d = 0;
}
// Если имеются две рассчитанные точки, строим линию в 3D
if (flag == 2) line (a - 1, b, e, a, b, d, pDC);
e = d;
}
}
}
void line (double a, double b, double c, double d, double e, double f, CDC *pDC)
{
double g, h; // первая точка на плоскости
double i, j; // вторая точка на плоскости
g = a * xb + b * yb + c * zb;
h = a * xc + b * yc + c * zc; // проекция первого вектора на ось Oy
i = d * xb + e * yb + f * zb;
j = d * xc + e * yc + f * zc; // проекция второго вектора на ось Oy
if (g > 1500) g = 1500;
if (g < -1500) g = -1500;
if (i > 1500) i = 1500;
if (i < -1500) i = -1500;
pDC -> MoveTo (400 - (int) h, 400 - (int) g);
pDC -> LineTo (400 - (int) j, 400 - (int) i);
}
double f1 (double x, double y)
{
double z;
if (y == 0) {flag = 0; return 0;} // область определения функции
z = x / y; // функция, график которой надо построить
if (flag < 2) flag++;
if (z > 100) {flag = 0; return 0;}
if (z < -100) {flag = 0; return 0;}
return z;
}