- •Перелік скорочень та визначень
- •Розділ і. Теоретичні відомості
- •1.1. Поняття навігації та навігаційної системи. Види нс.
- •1.2. Астрономічні методи навігації.
- •1.3. Радіотехнічні методи навігації.
- •1.4. Сучасні супутникові навігаційні системи.
- •1.5. Візуальні методи навігації.
- •1.6. Метод обчислення координат об'єкту з допомогою фотографування опорних точок.
- •1.7. Математичний опис технології.
- •1.6. Постановка задачі.
- •Розділ іі. Алгоритмізація
- •2.1. Основний алгоритм роботи програми.
- •2.2. Алгоритм математичних розрахунків.
- •Розділ ііі. Кодування
- •3.1. Створення проекту та розташування елементів інтерфейсу програми.
- •3.2. Кодування основної частини програми.
- •3.3. Кодування виводу координатної системи.
- •Розділ іv. Тестування
- •Висновки
- •Список використаної літератури
- •Додатки Додаток а. Файл реалізації aTriangulationDlg.Cpp
- •Додаток б. Файл реалізації Win2Dlg.Cpp
Додатки Додаток а. Файл реалізації aTriangulationDlg.Cpp
// ATriangulationDlg.cpp : файл реализации ATriangulationDlg.cpp
//
#include "stdafx.h"
#include "ATriangulation.h"
#include "ATriangulationDlg.h"
#include "Win2Dlg.h"
#include <atlimage.h>
#include <fstream>
#include <math.h>
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define M_PI 3.14159265358979323846
CImage image; //создание img
CString fileName; //путь к файлу с изображением
bool bClick=false; //флаг для click
long iPixDist=0;
//углы в радианах
double camAngle=0.9071; //угол обзора камеры по умолчанию
double aAngle=0, bAngle=0; //углы альфа и бета
double x=0, y=0; //искомые координаты
double sizeX, sizeY; //размеры системы координат
int N; //количество точек
double *X, *Y; //массивы координат опорных точек
int Index[3]; //массив для проверки введенных индексов ОТ
CWin2Dlg dlgWin2; //дескриптор второго окна
void CalculateCoords(double x1, double y1, double x2, double y2, double x3, double y3, double a, double b);
// Диалоговое окно CAboutDlg используется для описания сведений о приложении
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Данные диалогового окна
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // поддержка DDX/DDV
// Реализация
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// диалоговое окно CATriangulationDlg
CATriangulationDlg::CATriangulationDlg(CWnd* pParent /*=NULL*/)
: CDialog(CATriangulationDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CATriangulationDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CATriangulationDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDOK, &CATriangulationDlg::OnBnClickedOk)
ON_BN_CLICKED(IDC_BUTTON1, &CATriangulationDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDCANCEL, &CATriangulationDlg::OnBnClickedCancel)
ON_WM_LBUTTONDOWN()
ON_WM_CLOSE()
ON_BN_CLICKED(IDC_BUTTON2, &CATriangulationDlg::OnBnClickedButton2)
END_MESSAGE_MAP()
// обработчики сообщений CATriangulationDlg
BOOL CATriangulationDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Добавление пункта "О программе..." в системное меню.
// IDM_ABOUTBOX должен быть в пределах системной команды.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Задает значок для этого диалогового окна. Среда делает это автоматически,
// если главное окно приложения не является диалоговым
SetIcon(m_hIcon, TRUE); // Крупный значок
SetIcon(m_hIcon, FALSE); // Мелкий значок
//считывание параметров из файла конфигурации
ifstream config;
config.open("setup.cfg");
if(!config.good()) {
AfxMessageBox("Файл конфигурации не найден! Проверьте наличие файла setup.cfg в директории с программой и перезапустите ее!",0,0);
OnCancel();
}
char ftmp[16];
config >> ftmp; camAngle = atof(ftmp);
config >> ftmp; sizeX = atof(ftmp);
config >> ftmp; sizeY = atof(ftmp);
config >> ftmp; N = atof(ftmp);
//выделение памяти для массивов координат опорных точек
X = new double[N];
Y = new double[N];
for(int i=0; i<N ; i++) {
config >> ftmp;
X[i] = atof(ftmp);
config >> ftmp;
Y[i] = atof(ftmp);
}
return TRUE; // возврат значения TRUE, если фокус не передан элементу управления
}
void CATriangulationDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// При добавлении кнопки свертывания в диалоговое окно нужно воспользоваться приведенным ниже кодом,
// чтобы нарисовать значок. Для приложений MFC, использующих модель документов или представлений,
// это автоматически выполняется рабочей областью.
void CATriangulationDlg::OnPaint()
{
//перерисовка изображения после сворачивания окна
if(!image.Load(fileName)) {
image.AlphaBlend(this->GetDC()->m_hDC,0,0,640,480,0,0,image.GetWidth(),image.GetHeight());
image.Destroy();
}
if (IsIconic())
{
CPaintDC dc(this); // контекст устройства для рисования
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Выравнивание значка по центру клиентского прямоугольника
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Нарисуйте значок
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// Система вызывает эту функцию для получения отображения курсора при перемещении
// свернутого окна.
HCURSOR CATriangulationDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CATriangulationDlg::OnBnClickedOk() //загрузка изображения
{
CFileDialog File(TRUE); // открываем стандартный диалог
INT_PTR nResult = File.DoModal();
if(nResult == IDOK) {
//если загружаемый файл является изображением
if(!image.Load(File.GetPathName())) {
fileName.GetBuffer(1000);
fileName = File.GetPathName();
image.AlphaBlend(this->GetDC()->m_hDC,0,0,640,480,0,0,image.GetWidth(),image.GetHeight());
}
else {
AfxMessageBox("Файл не является изображением!",0,0);
}
}
image.Destroy();
}
void CATriangulationDlg::OnBnClickedCancel()
{
//очистка окна, сброс переменных
fileName = "";
fileName.ReleaseBuffer();
aAngle=0;
GetDlgItem(IDC_BUTTON1)->EnableWindow(true);
this->SetDlgItemText(IDC_STATIC1, "");
this->SetDlgItemText(IDC_STATIC2, "");
Invalidate();
dlgWin2.DestroyWindow();
}
void CATriangulationDlg::OnBnClickedButton1()
{
//кнопка неактивна после нажатия
GetDlgItem(IDC_BUTTON1)->EnableWindow(false);
}
void CATriangulationDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
char tmp[16];
char buf[4];
//если нажата кнопка "Нач. изм."
if(GetDlgItem(IDC_BUTTON1)->EnableWindow(false) != 0) {
//если произведено 2 нажатия мыши
if(bClick) {
GetDlgItem(IDC_BUTTON1)->EnableWindow(true);
iPixDist = abs(iPixDist-point.x);
//если вычисление первого угла не производились
if(aAngle==0) {
aAngle = (camAngle * (double)iPixDist) / 640;
sprintf(tmp, "%f", aAngle);
AfxMessageBox(strcat(tmp, " alpha"), 0, 0);
//получить координаты опорных точек
this->GetDlgItemText(IDC_EDIT1, buf, 4);
Index[0] = atoi(buf);
this->GetDlgItemText(IDC_EDIT2, buf, 4);
Index[1] = atoi(buf);
}
//если первый угол уже вычислен
else {
bAngle = (camAngle * (double)iPixDist) / 640;
sprintf(tmp, "%f", bAngle);
AfxMessageBox(strcat(tmp, " beta"), 0, 0);
//одна из точек обязательно должна быть общей
this->GetDlgItemText(IDC_EDIT1, buf, 4);
Index[2] = atoi(buf);
if(Index[2] == Index[0] || Index[2] == Index[1]) {
this->GetDlgItemText(IDC_EDIT2, buf, 4);
Index[2] = atoi(buf);
}
//вычисление искомых координат
CalculateCoords(X[Index[0]], Y[Index[0]], X[Index[1]], Y[Index[1]], X[Index[2]], Y[Index[2]], aAngle, bAngle);
//вывод на экран результата
sprintf(tmp, "%f", x);
this->SetDlgItemText(IDC_STATIC1, tmp);
sprintf(tmp, "%f", y);
this->SetDlgItemText(IDC_STATIC2, tmp);
aAngle = 0;
}
bClick = false;
}
else {
iPixDist = point.x;
bClick = true;
}
}
else {
GetDlgItem(IDC_BUTTON1)->EnableWindow(true);
}
}
void CalculateCoords(double x1, double y1, double x2, double y2, double x3, double y3, double a, double b)
{
double AB, BD, AD; //стороны
double f, f1, f2, la, lb; //углы
double R1, R2; //радиусы
//вычисление длин сторон с помощью известных координат
AB = sqrt(pow((x2-x1), 2) + pow((y2-y1), 2));
BD = sqrt(pow((x3-x2), 2) + pow((y3-y2), 2));
AD = sqrt(pow((x3-x1), 2) + pow((y3-y1), 2));
//радиусы окружностей, описанных вокруг первого и второго треугольников
R1 = AB / (2*sin(a));
R2 = BD / (2*sin(b));
f = acos((pow(AB,2)+pow(BD,2)-pow(AD,2))/(2*AB*BD));
if((y1-y3)*x2+(x3-x1)*y2+(x1*y3-x3*y1)>0)
f = 2*M_PI - acos((pow(AB,2)+pow(BD,2)-pow(AD,2))/(2*AB*BD));
la = atan(sin(2*M_PI-f-a-b) / (R1/R2+cos(2*M_PI-f-a-b)));
lb = 2*M_PI - a - b - f - la;
f1 = M_PI - a - la;
f2 = f - f1;
double AC, DC;
//вычисление сторон с помощью радиусов окружностей
AC = 2*R1*sin(f1);
DC = 2*R2*sin(f2);
//если координаты Y опорных точек совпадают
if(y1 == y3) {
x = (pow(AC, 2) - pow(DC, 2) - pow(x1, 2) + pow(x3, 2)) / (2*(x3-x1));
y = y1 + sqrt(pow(AC,2) — pow((x-x1),2));
if(x3<x1)
y = y1 - sqrt(pow(AC,2) - pow((x-x1),2));
}
//если координаты X опорных точек совпадают
else if(x1 == x3) {
y = (pow(AC, 2) - pow(DC, 2) - pow(y1, 2) + pow(y3, 2)) / (2*(y3-y1));
x = x1 - sqrt(pow(AC,2) — pow((y-y1),2));
if(y3>y1)
x = x1 - sqrt(pow(AC,2) - pow((y-y1),2));
}
//в остальных случаях
else {
double dA = pow(AC,2) - pow(DC,2) - pow(x1,2) - pow(y1,2) + pow(x3,2) + pow(y3,2);
double dB = 2*(x3-x1);
double dC = 2*(y3-y1);
double dG = pow(dA,2) - 2*dA*dC*y1 + pow(dC,2)*pow(x1,2) + pow(dC,2)*pow(y1,2) - pow(dC,2)*pow(AC,2); //c
double dE = 2*(dB*dC*y1 - dA*dB - x1*pow(dC,2)); //b
double dF = pow(dC,2) + pow(dB,2); //a
//a*(x^2) + b*x + c = 0
double D = sqrt(pow(dE,2) - 4*dF*dG);
x = (-dE + D) / (2*dF);
y = (dA - x*dB) / dC;
if(x3<x1 && y3>y1) {
x = (-dE - D) / (2*dF);
y = (dA - x*dB) / dC;
}
}
}
void CATriangulationDlg::OnClose()
{
//освобождаем память при закрытии приложения
fileName.ReleaseBuffer();
delete[] X;
delete[] Y;
DestroyWindow();
}
void CATriangulationDlg::OnBnClickedButton2()
{
//создание второго диалогового окна
dlgWin2.DestroyWindow();
dlgWin2.Create(IDD_WIN2,this);
dlgWin2.ShowWindow(SW_SHOW);
}