📄 board.cpp
字号:
SelectObject(hDC, m_hpen3);
DrawVector(hDC, rc, m_angles);
}
RestoreDC(hDC, n_save_dc);
}
void Board::DrawBottomDesc(HDC hDC, RECT& rc)
{
if ((training_mode == m_mode || trained_mode == m_mode)
&& m_update_bottom_desk)
{
BitBlt(hDC, 0, 0, rc.right - rc.left, rc.bottom - rc.top, m_hMemDC4, 0, 0, SRCCOPY);
}
else
{
int n_save_dc = SaveDC(hDC);
SelectObject(hDC, m_hbrh2);
SelectObject(hDC, m_hpen2);
Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
if (recognized_success == m_mode)
{
// draw a recognized pattern
vector_real_t vec(NUMBER_OF_ANGLES);
for (unsigned n = 0; n < vec.size(); ++n)
vec[n] = pattern_data[m_winners[0].m_id][n];
SelectObject(hDC, m_hpen3);
DrawVector(hDC, rc, vec);
}
RestoreDC(hDC, n_save_dc);
}
}
void Board::DrawStatusInfo(HDC hDC, RECT& rc)
{
int n_save_dc = SaveDC(hDC);
SelectObject(hDC, m_hbrh2);
SelectObject(hDC, m_hpen2);
Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
COLORREF clrTxt = RGB(0, 0, 0);
TCHAR buf[512] = {0};
if (recognizing_mode == m_mode)
sprintf(buf, "points %u", m_path.size());
else if (training_mode == m_mode && m_errors.size())
sprintf(buf, "error: %f", m_errors.back());
else if (trained_mode == m_mode && m_errors.size())
sprintf(buf, "training cycles: %u, mean square error: %f", m_train_cycles, m_errors.back());
else if (recognized_success == m_mode)
{
clrTxt = RGB(0, 0, 255);
sprintf(buf, "recognition is successful: %s (%f)",
pattern_names[m_winners[0].m_id], m_winners[0].m_probability);
}
else if (recognized_fail == m_mode)
{
clrTxt = RGB(255, 0, 0);
sprintf(buf, "unable to recognize anything, the best is %s (%f), points %u",
pattern_names[m_winners[0].m_id], m_winners[0].m_probability, m_path.size());
}
else
sprintf(buf, "untrained net");
if (m_info.size())
{
_tcscat (buf, _T(" - "));
_tcsncat(buf, m_info.c_str(), sizeof(buf)/sizeof(buf[0]) - _tcslen(buf));
}
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, clrTxt);
SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
SIZE sz;
GetTextExtentPoint32(hDC, buf, lstrlen(buf), &sz);
int x = rc.left + 3;
int y = rc.top + ((rc.bottom - rc.top) - sz.cy) / 2;
ExtTextOut(hDC, x, y, ETO_CLIPPED, &rc, buf, lstrlen(buf), 0);
RestoreDC(hDC, n_save_dc);
}
void Board::DrawVector(HDC hDC, RECT& rc, vector_real_t& vec)
{
typedef path_t::iterator iterator;
path_t path;
vector_to_path(rc, vec, path);
iterator i = path.begin();
MoveToEx(hDC, (*i).x, (*i).y, 0);
++i;
unsigned n = 0;
for (; i != path.end(); ++i, ++n)
{
SelectObject(hDC, m_hpdesk[n / 4]);
LineTo (hDC, (*i).x, (*i).y);
SetPixel(hDC, (*i).x, (*i).y, RGB(0, 0, 255));
}
}
/////////////////////////////////////////////////
bool Board::TransfromPath()
{
typedef path_t::iterator iterator;
m_path2.assign(m_path.begin(), m_path.end());
if (NUMBER_OF_ANCHOR_POINTS > m_path.size())
{
// todo : stretch path or warning message;
// m_path.clear();
m_path2.clear();
m_mode = recognizing_mode;
return false;
}
else if (NUMBER_OF_ANCHOR_POINTS < m_path.size())
{
// smooth path
// finds smallest interval and replaces two points on median point
while (m_path2.size() > NUMBER_OF_ANCHOR_POINTS)
{
double d;
double d_min = std::numeric_limits<double>::max();
iterator p_min = m_path2.begin();
++p_min;
iterator p = p_min;
iterator i = p_min;
++i;
iterator last = m_path2.end();
--last;
for (; i != last; ++i)
{
d = sqrt(pow((*p).x - (*i).x, 2) + pow((*p).y - (*i).y, 2));
if (d < d_min)
{
d_min = d;
p_min = p;
}
p = i;
}
p = p_min;
i = ++p_min;
POINT pt = {((*p).x + (*i).x) / 2, ((*p).y + (*i).y) / 2};
*i = pt; // changes coord of a base point
m_path2.erase(p); // erases an odd point
}
}
else
{
// nothing
}
_ASSERTE(m_path2.size() == NUMBER_OF_ANCHOR_POINTS);
// computes angles, cosines and sines
iterator i = m_path2.begin();
iterator p = i++;
unsigned n = 0;
for (; i != m_path2.end(); ++i, ++n)
{
POINT pt2 = (*i);
POINT pt1 = (*p);
pt2.x -= pt1.x;
pt2.y -= pt1.y;
if (pt2.x || pt2.y)
{
m_cosines[n] = float(pt2.y / sqrt(pt2.x * pt2.x + pt2.y * pt2.y));
m_sinuses[n] = (float)sqrt(1. - m_cosines[n] * m_cosines[n]);
if (pt2.x < 0) m_sinuses[n] = - m_sinuses[n];
m_angles[n] = float(acos(m_cosines[n]) * 180. / pi);
if (pt2.x < 0) m_angles[n] = 360.f - m_angles[n];
}
else
{
m_cosines[n] = 1;
m_sinuses[n] = 0;
m_angles[n] = 0;
}
p = i;
_ASSERTE(m_cosines[n] <= 1.);
_ASSERTE(m_cosines[n] >= -1.);
_ASSERTE(m_sinuses[n] <= 1.);
_ASSERTE(m_sinuses[n] >= -1.);
_ASSERTE(m_angles [n] <= 360.);
_ASSERTE(m_angles [n] >= 0.);
}
return true;
}
///////////////////////////////////////////////////////////
unsigned Board::StartTraining()
{
m_mode = training_mode;
m_update_top_desk = false;
m_update_bottom_desk = false;
m_path.clear();
m_path2.clear();
m_max_error = 0;
m_errors.clear();
m_errors.reserve(m_rcMemDC.right - m_rcMemDC.left - DESK_WIDTH - 6);
// Refresh();
return m_rcMemDC.right - m_rcMemDC.left - DESK_WIDTH - 6;
}
void Board::UpdateTrainingError(float current_error)
{
m_max_error = std::_MAX(m_max_error, current_error);
m_errors.push_back(current_error);
// Refresh();
}
void Board::UpdateTrainingVector(vector_real_t& vec)
{
_ASSERTE(vec.size() == m_angles.size());
typedef vector_real_t::iterator iterator;
for (iterator to = m_angles.begin(), from = vec.begin(); to != m_angles.end(); ++to, ++from)
{
*to = *from;
}
m_update_top_desk = true;
}
void Board::UpdateTrainingWeight(vector_real_t::iterator w_begin, vector_real_t::iterator w_end)
{
_ASSERTE((w_end - w_begin) <= DESK_WIDTH * DESK_HEIGHT);
typedef vector_real_t::iterator iterator;
int n_save_dc = SaveDC(m_hMemDC4);
RECT rc = {0, 0, DESK_WIDTH, DESK_HEIGHT};
#define SPACE 2
SelectObject(m_hMemDC4, m_hbrh2);
SelectObject(m_hMemDC4, m_hpen2);
Rectangle(m_hMemDC4, rc.left, rc.top, rc.right, rc.bottom);
unsigned dim = (unsigned)sqrt(w_end - w_begin);
unsigned left = (DESK_WIDTH - dim * SPACE) / 2;
unsigned top = (DESK_HEIGHT - dim * SPACE) / 2;
iterator i = w_begin;
for (unsigned x = left; x < left + dim * SPACE; x += SPACE)
for (unsigned y = top; y < top + dim * SPACE; y += SPACE)
{
float f = *i;
COLORREF clr;
if (fabs(f) > 1.)
clr = f < 0. ? RGB(255, 255, 0) : RGB(0, 0, 255) ;
else
clr = f < 0. ? RGB(f * 255., 0, 0) : RGB(0, f * 255., 0);
SetPixel(m_hMemDC4, x, y, clr);
SetPixel(m_hMemDC4, x + 0, y + 1, clr);
SetPixel(m_hMemDC4, x + 1, y + 0, clr);
SetPixel(m_hMemDC4, x + 1, y + 1, clr);
++i;
}
_ASSERTE(i <= w_end);
RestoreDC(m_hMemDC4, n_save_dc);
m_update_bottom_desk = true;
}
void Board::StopTraining(unsigned last_cycle)
{
// m_mode = recognizing_mode;
// m_errors.clear();
m_mode = trained_mode;
m_train_cycles = last_cycle + 1; // 0..last_cycle
}
void Board::StartMouseRecord()
{
// CWindow(GetParent()).SendMessage(WM_COMMAND, MAKEWPARAM(ID_STOP, 0));
m_path.clear();
m_path2.clear();
if (untrained_mode != m_mode)
m_mode = recognizing_mode;
Refresh();
}
void Board::AddMouseRecord(POINT pt)
{
m_path.push_back(pt);
Refresh();
}
void Board::StopMouseRecord()
{
bool r = TransfromPath();
if (untrained_mode != m_mode && r)
{
CWindow(GetParent()).SendMessage(WM_COMMAND, MAKEWPARAM(ID_RECOGNIZE, 0));
}
Refresh();
}
///////////////////////////////////////
// static
Board::vector_to_path(RECT& rc, vector_real_t& vec, path_t& path)
{
typedef vector_real_t::iterator iterator;
int y = 0, x = 0, cx = rc.right - rc.left, cy = rc.bottom - rc.top;
RECT borders = {0};
iterator i;
double dx = (double)cx / (vec.size() - 1);
double dy = (double)cy / (vec.size() - 1);
for (i = vec.begin(); i != vec.end(); ++i)
{
double angle = (double)*i;
x += int(dx * sin(angle * (pi / 180.)));
y += int(dy * cos(angle * (pi / 180.)));
if (borders.left > x) borders.left = x;
if (borders.right < x) borders.right = x;
if (borders.top > y) borders.top = y;
if (borders.bottom < y) borders.bottom = y;
}
x = - borders.left + (cx - (borders.right - borders.left)) / 2;
y = - borders.top + (cy - (borders.bottom - borders.top)) / 2;
POINT pt = {x, y};
path.push_back(pt);
unsigned n = 0;
for (i = vec.begin(); i != vec.end(); ++i, ++n)
{
double angle = (double)*i;
x += int(dx * sin(angle * (pi / 180.)));
y += int(dy * cos(angle * (pi / 180.)));
pt.x = x; pt.y = y;
path.push_back(pt);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -