2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2
 
 
Сообщение13.04.2006, 15:04 


13/09/05
153
Москва
Цитата:
То есть, когда я изменяю тело CMainFrm, то мне надо вносить изменения и в Bmp1.h, так что ли? И что надо туда дописать? Ведь, судя по тому, что до создания сплиттера, CMainFrm нормально работал с Cbmp1, хедер уже был подключен?


Да нет, не совсем. CMainFrm понятия не имеет про Ваш вид и Ваш документ, а оперирует только с базовыми CView и CDocument. Вид и документ создаются в теле CMyApp в InitInstance -
Код:
CSingleDocTemplate* pDocTemplate;
   pDocTemplate = new CSingleDocTemplate(
      IDR_MAINFRAME,
      RUNTIME_CLASS(CMyDoc),
      RUNTIME_CLASS(CMainFrame),       // main SDI frame window
      RUNTIME_CLASS(CMyView));
   AddDocTemplate(pDocTemplate);

и файле CMyApp.cpp подключаются CMyDoc.h и CMyView.h. При создании MFC-проекта генерятся несколько файлов - вид, документ и приложение и автоматически в реализацию приложения добавляется код -
Код:
#include "MainFrm.h"
#include "MyDoc.h"
#include "MyView.h"


Хедер MyView.h в CMainFrame при создании проекта не добавляется.
Но для создания сплиттера ему нужно добавить нужный вид -
Код:
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CTestSplitterView), CSize(rect.Width()/2, rect.Height()), pContext))

Следовательно нужно также определить, что за зверь этот CTestSplitterView, для чего добавляем в реализацию (ну или в хедер) CMainFrame #include "TestSplitterView.h".

 Профиль  
                  
 
 
Сообщение15.04.2006, 08:04 
Аватара пользователя


18/02/06
61
Moscow
Слушай, а нельзя создать сразу пустой проект, а потом внести туда файлы из твоего проекта?
А то у меня по умолчанию добавляется куча файлов, а я их не могу удалить. Тогда я просто беру файлы из папки TwoView и из проводника копирую их в папку своего проекта (при этом часть файлов моего проекта заменяется твоими, но тогда при компиляции мне выдается куча ошибок, и все равно ничего не работает) ((((
Я пробовала править хедеры вручную, чтобы они ссылались на твои файлы, но количество ошибок только растет...

И еще вопросы:
1. Откуда он взял эти 2 текста: "Это правое (левое) окно" Я что-то я исходниках нигде такого не нашла
Код:
m_strText = _T("");  и где это _Топределено?


2. Зачем нужны файлы BufferDC.cpp и BufferDC.h Только для создания рамочек?

3. Почему строка заливки
Код:
pDC->FillSolidRect(rect, (m_bSelected)? RGB(0, 250, 250) : RGB(255, 255, 255));

Присутствует сразу в двух файлах SecondView.cpp TestWnd.cpp?
Разве в одном ее поместить недостаточно?

4. Как мне обращаться к каждому окну, если я хочу открыть картинку из файла? В однооконном приложении я просто вставляла в главный файл имя_проекта.cpp
Следующий код:
Код:
BMIH=m_dibFile.m_lpBMIH;

if(BMIH)
   {
      BitCount=BMIH->biBitCount;      // число бит
      Width=BMIH->biWidth;            // ширина
      Height=BMIH->biHeight;           // высота
      Size=m_dibFile.GetSizeImage();  // размер
      LpIm=m_dibFile.m_lpImage;       // А ЭЖТО ЧТО ЗА ПАРАМЕТР?
      Line=(Size*8)/Height;
      Color1=(int *)(BMIH+1);
      Color2=Color1+1;
      PalettSize=m_dibFile.m_nColorTableEntries; // Палитра
   }


И все работало, а теперь он не выводит файл ни в одно окно.

 Профиль  
                  
 
 
Сообщение16.04.2006, 14:09 
Аватара пользователя


18/02/06
61
Moscow
Вот, у меня теперь почти все получается, только осталась 1 проблема:
Class wizard не хочет добавлять вот эти строчки в файл MyProj.h
Код:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnSize(UINT nType, int cx, int cy);

Вместо этого там написано
Код:
// NOTE - the ClassWizard will add and remove member functions here.
      //    DO NOT EDIT what you see in these blocks of generated code !


Но когда я их добавляю вручную, файл компилится. Pgfnj при попытке запуска выдается сообщение о критической ошибке, и окно закрывается.

 Профиль  
                  
 
 
Сообщение17.04.2006, 13:44 


13/09/05
153
Москва
Что я попытался показать в этом проекте -
1. Если не нужен сплиттер, то можно в вид внедрить еще несколько видов или CWnd-derived классов, и они будут сами себя рисовать и обрабатывать все сообщения, относящиеся к ним. То есть первоначальный вид CTwoViewView является только обладателем мемберов
Код:
CTestWnd m_wndLeft;
CSecondView m_wndRight;
, а всю функциональность выполянют сами мемберы.

2. Вид CSecondView и CTestWnd, используемые в качестве мемберов, содержат одинаковую отрисовку (два идентичных метода), чтобы показать, что в уже существующий вид можно вставить как еще один вид, так и CWnd-derived, и разницы никакой.

Цитата:
Вот, у меня теперь почти все получается, только осталась 1 проблема:
Class wizard не хочет добавлять вот эти строчки в файл MyProj.h
Код:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnSize(UINT nType, int cx, int cy);

Вместо этого там написано Код:
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !


Методы нужно добавлять с помощью класс-визарда (Ctrl+W), а можно и просто вставить копированием.

Код:
//{{AFX_VIRTUAL(CTwoViewView)
   public:
   virtual void OnDraw(CDC* pDC);  // overridden to draw this view
   virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
   protected:
   virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
   virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
   virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
   //}}AFX_VIRTUAL

Все, что находится внутри AFX_VIRTUAL - это методы, добавленные Class Wizard'ом.
Если мы что-то добавляем в ручную, то это лучше добавлять после //}}AFX_VIRTUAL, иначе
Class Wizard будет глючить.
Тоже самое с обработчиками сообщений - их визард добавляет внутрь блока AFX_MSG -
Код:
//{{AFX_MSG(CTwoViewView)
   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
   afx_msg BOOL OnEraseBkgnd(CDC* pDC);
   afx_msg void OnSize(UINT nType, int cx, int cy);
   //}}AFX_MSG
   DECLARE_MESSAGE_MAP()

Если хотим добавить что-то свое путем копирования, лучше вставлять после //}}AFX_MSG, перед DECLARE_MESSAGE_MAP().

По поводу проекта - я предлагаю Вам создать новый MFC-проект с таким же названием (TwoView). Затем закрыть студию (или закрыть проект), и копирнуть все файлы в Ваш новый проект. Затем открываем проект и добавляем файлы (BufferDc, TestWnd, SecondView и прочее), для чего используем меню Project->Add to Project -> Files и там выделяем нужные файлы. Можно выделить все файлы, студия сама решит что нужно добавить, а что нет (ругнется типа, такие-то файлы уже добавлены:)).

Цитата:
m_strText = _T("");
- это моя дурацкая привычка. Это макрос создания строки.

Цитата:
Зачем нужны файлы BufferDC.cpp и BufferDC.h Только для создания рамочек?
- Да. BufferDC - это класс для буферизации изображения, устраняет косяки с морганием экрана при частой перерисовке и закрашивании. То есть при его использовании Вы рисуете в виртуальный контекст устройства, а в его деструкторе вызывается копирование из памяти BufferDC в текущий CDC.

Обращаться к каждому окну - посредством главного вида CTwoViewView - он является владельцем этих окон. Самое простое, что приходит в голову -
Код:
// Добавляем в CTwoViewView две новых функции -
CTestWnd* GetLeftWnd(){return &m_wndLeft;}
CSecondView* GetLeftWnd(){return &m_wndRight;}

// Пример обращения к мемберам из документа -
void CTwoViewDoc::AddBitmap(HBITMAP hBmp)
{
   CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
   CTwoViewView* pView = DYNAMIC_DOWNCAST(CTwoViewView , pFrame->GetActiveView());
   if (pView)
   {
      CTestWnd* pLeftWnd = pView->GetLeftWnd();
      pLeftWnd->AddBitmap(hBmp);
   }
}

// Или сделать в CTwoViewView два метода -
void AddBitmapToLeftWnd(HBITMAP hBmp);
void AddBitmapToRightWnd(HBITMAP hBmp);

// И тогда -
void CTwoViewDoc::AddBitmap(HBITMAP hBmp)
{
   CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
   CTwoViewView* pView = DYNAMIC_DOWNCAST(CTwoViewView , pFrame->GetActiveView());
   if (pView)
      pView->AddBitmapToLeftWnd(hBmp);
}

 Профиль  
                  
 
 
Сообщение22.04.2006, 09:16 
Аватара пользователя


18/02/06
61
Moscow
То есть я в функцию void CTwoViewDoc::AddBitmap(HBITMAP hBmp) в качестве hbmp передаю m_dibFile.m_lpBMIH или m_dibFile.m_lpImage? И тогда можно забыть, что у нас 2 окна, и работать с одним.

И еще такой алгоритмический вопрос:
Допустим, у меня есть список точек с координатами. Мне надо из них построить такие структуры:
берем произвольную точки из списка в качестве центра, а потом добавляем в структуру все точки, расстояние до которых не больше заданного.
Информация о точках: координаты+тип точки (число 1 или 2) - то есть мой класс точки будет производным от CPoint ?

Но вот в чем проблема: мне еще нужно куда-то добавить информацию об углах между точками и о количестве линий между ними, а также информацию о числе точек в структуре.
Это нужно, чтобы сравнивать 2 построенных структуры по этим параметрам.

Никак не соображу, у меня с БД всегда плохо было ))) Как бы представить инфу.
Вот мой вариант
Класс Звезда
1.Содержит переменные класса ТипТочка (коорд+тип)
2. Содержит матрицу (как вот ее задать, чтобы она была переменного размера - про масссивы-то я знаю...).
В матрице столбцы и строки - это номера ТипТочек в звезде.
На пересечениии столбца и строки - объект класса УголРасст (который содержит 2 переменные-члена - угол и число линий)
3. Содержит переменную - член: число ТипТочек в звезде

 Профиль  
                  
 
 
Сообщение22.04.2006, 13:22 


13/09/05
153
Москва
Цитата:
То есть я в функцию void CTwoViewDoc::AddBitmap(HBITMAP hBmp) в качестве hbmp передаю m_dibFile.m_lpBMIH или m_dibFile.m_lpImage? И тогда можно забыть, что у нас 2 окна, и работать с одним.


Если Вам нужно отображать картинки и в левом, и в правом окне, я бы предложил сделать что-нить типа <code>
void CTwoViewDoc::AddBitmapToLeftWnd(HBITMAP hBmp);
void CTwoViewDoc::AddBitmapToRightWnd(HBITMAP hBmp);
// или
void CTwoViewDoc::AddBitmap(HBITMAP hBmp, BOOL bAddToLeft);
[/code]

От CPoint лучше вообще ничего не наследовать. Проще сделать свой класс с мембером типа CPoint -
Код:
class CMyPoint
{
public:
   CMyPoint();
   virtual ~CMyPoint();

   UINT GetType() const {return m_nType;}
   CPoint GetPoint() const {return m_ptPoint;}
   .........................
private:
   UINT m_nType;
   CPoint m_ptPoint;
// и прочие данные
   .........................
}


Цитата:
Никак не соображу, у меня с БД всегда плохо было ))) Как бы представить инфу.

Тут же все просто :), структура данных очень простая -
Код:
class CMyPointConnection
{
public:
   CMyPointConnection(CMyPoint* pPoint1, CMyPoint* pPoint2, int nLineNumber)
   {
      ASSERT(pPoint1 && pPoint2);
      m_pPoint1 = pPoint1;
      m_pPoint2 = pPoint2;
      m_nLineNumber = nLineNumber;
      CPoint delta = pPoint2->GetPoint() - pPoint1->GetPoint();
      m_dAngle = atan2(delta.y, delta.x);
   }
   virtual ~CMyPointConnection(){};
   
   CMyPoint* GetPoint1() const {return m_pPoint1;}
   CMyPoint* GetPoint2() const {return m_pPoint2;}
   int GetLineNumber() const {return m_nLineNumber;}
   double GetAngle() const {return m_dAngle;}
   
private:
   CMyPoint* m_pPoint1;
   CMyPoint* m_pPoint2;
   int m_nLineNumber;
   double m_dAngle;
}

typedef std::map<std::pair<CMyPoint*, CMyPoint*>, CMyPointConnection*> CMyConnectionMap;

class CMyStar
{
public:
   CMyStar(){}
   virtual ~CMyStar()
   {
      DeleteAllConnections();//удаляем созданные нами в AddConnection соединения
   }

   BOOL AddPoint(CMyPoint* pPoint)
   {
      BOOL bAdd = FALSE;
// здесь можно проверку сделать на наличие такого узла
      if (нету такого узла)
      {
         bAdd = TRUE;
         m_Points.push_back(pPoint);
      }
      return bAdd;
   }
   BOOL DeletePoint(CMyPoint* pPoint)
   {
      BOOL bDelete = FALSE;
      for (std::vector<CMyPoint* >::iterator iter = m_Points.begin(); iter != m_Points.end(); iter++)
      {
         if (*iter == pPoint)
         {
            bDelete = TRUE;
            m_Points.erase(iter);
            break;
         }
      }
      return bDelete;
   }
   
   BOOL AddConnection(CMyPoint* pPoint1, CMyPoint* pPoint2, int nLineNumber)
   {
      BOOL bAdd = FALSE;
      ASSERT(pPoint1 && pPoint2);
      if (m_Connections.find(std::make_pair(pPoint1, pPoint2)) == m_Connections.end() &&
         m_Connections.find(std::make_pair(pPoint2, pPoint1)) == m_Connections.end())
      {
         bAdd = TRUE;
         CMyPointConnection* pNewConnection = new CMyPointConnection(pPoint1, pPoint2, nLineNumber);
         m_Connections.insert(std::make_pair(pPoint1, pPoint2), pNewConnection);
      }
      return bAdd;
   }
   
   BOOL DeleteConnection(CMyPoint* pPoint1, CMyPoint* pPoint2)
   {
      BOOL bDelete = FALSE;
      ASSERT(pPoint1 && pPoint2);
      CMyConnectionMap::iterator iter1 = m_Connections.find(std::make_pair(pPoint1, pPoint2));
      CMyConnectionMap::iterator iter2 = m_Connections.find(std::make_pair(pPoint2, pPoint1));
      if (iter1 != m_Connections.end())
      {
         bDelete = TRUE;
         delete iter1->second;//iter1->second - это CMyPointConnection* pNewConnection, который мы создали в AddConnection
         m_Connections.erase(iter1);
      }
      if (iter2 != m_Connections.end())
      {
         bDelete = TRUE;
         delete iter2->second;//iter2->second - это CMyPointConnection* pNewConnection, который мы создали в AddConnection
         m_Connections.erase(iter2);
      }
      return bDelete;
   }
   
   void DeleteAllConnections()
   {
      for (CMyConnectionMap::iterator iter = m_Connections.begin(); iter != m_Connections.end(); iter++)
         delete iter->second;
      m_Connections.clear();
   }
   
   void Draw(CDC* pDC)
   {
      for (CMyConnectionMap::iterator iter = m_Connections.begin(); iter != m_Connections.end(); iter++)
      {
         pDC->MoveTo(iter->second->GetPoint1()->GetPoint());
         pDC->LineTo(iter->second->GetPoint2()->GetPoint());
      }
   }
   .........................
private:
   std::vector<CMyPoint*> m_Points;
   CMyConnectionMap m_Connections;
}

 Профиль  
                  
 
 
Сообщение22.04.2006, 20:01 
Аватара пользователя


18/02/06
61
Moscow
Ой, МАМОЧКИ! И сколько же времени у тебя ушло нанаписание этого куска кода? :shock:

 Профиль  
                  
 
 
Сообщение23.04.2006, 18:38 
Аватара пользователя


18/02/06
61
Moscow
Вот! Я тут создала диалоговое окошко для открытия 2х файлов, но у меня не получается вот что:

1.После выбора файла его имя должно появляться в текстовом окошке слева.
2.
Правее надписи результат я хочу создать еще 1 статическое поле, в котором тоже должно выводиться имя файла. А у меня ничего не выводится.
Код:
if (fileDlg1.DoModal()==IDOK)
   {
   CStatic m_static;
   CRect rect1(74,81,73,8);
   m_static.Create(fileDlg1.m_ofn.lpstrFile,WS_CHILD|WS_VISIBLE|SS_LEFT,rect1,this,IDC_STATIC);

   }

Вот, я сюда выложила свой проект:
http://xatkaonthenet.narod.ru/file2.rar
А это - то, что у меня получилось для 1 окошка (без сплиттера).
http://xatkaonthenet.narod.ru/GoldFinger.rar
Вот доделаю диалог - и будет то же для TwoView!

Внимание! Файлы вылодены на Народе, поэтому либо качай стандартным загрузчиком IE, либо убери reference у dowload managera

 Профиль  
                  
 
 
Сообщение24.04.2006, 15:16 


13/09/05
153
Москва
Цитата:
Ой, МАМОЧКИ! И сколько же времени у тебя ушло нанаписание этого куска кода?

Минут 30, писал из головы, возможны ляпы.
Несмотря в преокты из приведенного кода вижу два вещи -
1. У CFileDialog есть вот такие методы -
Код:
GetPathName - Returns the full path of the selected file.
GetFileName - Returns the filename of the selected file.
GetFileExt - Returns the file extension of the selected file.
GetFileTitle - Returns the title of the selected file.

2. По хорошему, при открытии-сохранении файлов нужно довать пользотелю некоторый выбор по расширению файла, и тогда строка фильтра может иметь вид -
Код:
CString strFilter = "Bitmaps (*.bmp)|*.bmp|All Files (*.*)|*.*||";

Вообще строка фильтра должна иметь вид по MSDN -
Цитата:
The lpszFilter parameter is used to determine the type of filename a file must have to be displayed in the file list box. The first string in the string pair describes the filter; the second string indicates the file extension to use. Multiple extensions may be specified using ‘;’ as the delimiter. The string ends with two ‘|’ characters, followed by a NULL character. You can also use a CString object for this parameter.

For example, Microsoft Excel permits users to open files with extensions .XLC (chart) or .XLS (worksheet), among others. The filter for Excel could be written as:

static char BASED_CODE szFilter[] = "Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xls)|*.xls|Data Files (*.xlc;*.xls)|*.xlc; *.xls|All Files (*.*)|*.*||";

То есть строка имеет вид - "_Строка_поянения_|_фильтр_|" и т.д., а в конце "|".

3. Вы создаете объект CStatic внутри тела оператора If и жить этот объект будет тоже только внутри него, при выходе из этого блока вызовется его деструктор.
Если нужно что-нить куда-нить вывести -
1. Делаем в шаблоне диалога некий control, можно от CStatic, а затем -
Код:
CWnd* pMyCtrl = GetDlgItem(IDC_MYCTRL);
if (pMyCtrl)
   pMyCtrl->SetWindowText(fileDlg1.GetFileName());

2. Можно добавить в диалог объект типа edit-box, и для него можно использовать следующее. Во-первых создать в диалоге объект, используя Class Wizard (Ctrl + W), типа CEdit, и тогда работать с ним как с обычным окном - m_ctrlEdit.SetWindowText(str); или связать с edit-box какую-нить строку m_strEdit (используя Class Wizard ), и тогда -
Код:
m_strEdit = "123";
UpdateData(FALSE);


Забираем данные с помощью UpdateData(TRUE);

Проекты Ваши у меня не открылись (is invalid and will be removed from project workspace...), причем студия у меня вроде как нормальная, по крайней мере, практически все проекты из сайтов типа CodeProject и CodeGuru у меня открываются нормально:)) Значит глюк у Вас какой-то со студией:)
Для проекта File2 сделал следующее - создал новый проект с таким же названием и добавил в него все, кроме файлов .dsp, .dsw.
Соответственно для контрола IDC_EDIT2 добавил с класс-визарда мембер m_ctrlEdit2, и изменил два метода OnButton1 и OnButton2, чтобы проиллюстрировать все выше сказанное -
Код:

void CFile2Dlg::OnButton1()
{
   CString strTitle = "Open Bitmap #1";
   CString strFilter = "Bitmaps (*.bmp)|*.bmp|All Files (*.*)|*.*||";
   CFileDialog Dlg(TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, strFilter);
   Dlg.m_ofn.lpstrTitle = strTitle;
   Dlg.m_ofn.Flags |= OFN_HIDEREADONLY;
   if (Dlg.DoModal() == IDOK)
   {
      CWnd* pWnd = GetDlgItem(IDC_EDIT1);
      if (pWnd)
         pWnd->SetWindowText(Dlg.GetPathName());
   }
}

void CFile2Dlg::OnButton2()
{
   CString strTitle = "Open Bitmap #2";
   CString strFilter = "Bitmaps (*.bmp)|*.bmp|All Files (*.*)|*.*||";
   CFileDialog Dlg(TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, strFilter);
   Dlg.m_ofn.lpstrTitle = strTitle;
   Dlg.m_ofn.Flags |= OFN_HIDEREADONLY;
   if (Dlg.DoModal() == IDOK)
   {
      m_ctrlEdit2.SetWindowText(Dlg.GetPathName());
   }
}

 Профиль  
                  
 
 
Сообщение24.04.2006, 21:37 
Аватара пользователя


18/02/06
61
Moscow
А что по поводу второго проекта? Как думаешь, нормально написано? Я старалась! :lol:

 Профиль  
                  
 
 
Сообщение25.04.2006, 11:51 


13/09/05
153
Москва
Бегло посмотрел и есть несколько замечаний:
1. В MFC принята такая идеология - документ хранит и работает с данными, вид только рисует. Обработка тулбара и прочих сообщений - все, что относиться к отображению, обрабатывает вид, а все, что относится к работе с данными, отображению диалогов со свойствами, отображение диалогов с инфой - задача документа.
Документ - один единственный и виден всем видам. Видов даже в SDI (Single Document Interface) может быть несколько и прямое обращение к ним из документа усложняется.
Обычно CMainFrm владеет видами и всякими окошками (статус-бар и прочее), а следовательно связь между документом и последними можно сделать через CMainFrm, для чего в CMainFrm добавляем соответвствующие методы и используем его как "фасад" для обращения к этих окошкам.
Сохранение файлов, открытие и прочее - это непосредственная задача документа, в нем и методы соответствующие есть.

2. Зачем Вы используете alloc и free. Есть много причин (все не помню), почему следует использовать new и delete. А так вы делаете проект в MFC, то вам вообще стоит забыть про них. В MFC для отладки утечек памяти в начале каждого файла добавляется вот такой код -
Код:
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

В Debug'е при выходе из приложения MFC в случае обнаружения утечек памяти выводит имя исходника, строку и все прочее, и Вы сразу видите, где и что забыли подчистить.

3. В виде объявлено куча глобальных функций - по-идее, это обработка изображения, они должны быть в документе. Но не в этом дело - раз уж мы используем классы документа и вида и помещаем этот код в .cpp, то почему не следать их мембер-функциями документа, скажем приватными?:))

4. В виде объявлено куча глобальных переменных (я говорю не про константы, а именно переменные Parts и прочее), которые используются в глобальных функциях. Если исключить глобальные функции, то эти данные хранят данные, которые были получены в результате обработки (т.е. в документе) и должны по идее храниться, создаваться и убаваться документом, т.е. быть его мемберами.

5. В OnMouseWheel есть вызов OnInitialUpdate() - это в корне неправильно, так как эта функция по-идее вызывается единыжды при создании вида -
Цитата:
Called by the framework after the view is first attached to the document, but before the view is initially displayed.


6. В коде отрисовки OnDraw Вы по несколько раз подряд включаете одни и теже CPen и CBrush. Это незачем - один раз включили некоторый CPen, и потом им рисуем, нужен другой - поменяли, продолжаем рисовать.

7. По хорошему, при смене кисти и карандаша нужно сохранять предыдущие, чтоб по окончанию нашего творчества вернуть исходные. Для этого есть много способов, классика выглядит вот так:
Код:
void OnDraw(CDC* pDC)
{
   CPen pen(PS_SOLID, 1, RGB(255, 0, 0));
   CPen* pOldPen = pDC->SelectObject(&pen);
//   что-нить рисуем
.............................
   CPen pen2(PS_SOLID, 1, RGB(0, 0, 255));
   pDC->SelectObject(&pen2);// включаем другую
//   что-нить рисуем2
....................................
//   и возвращаем все на место
   pDC->SelectObject(pOldPen);
}

Можно также использовать SaveDC и RestoreDC. Есть в инете классы умных кистей и карандашей, в конструкторе которого стоит сохранение текущего CPen (pOldPen ), а в деструкторе - SelectObject сохраненного pOldPen.

8. Если нужно нарисовать большое количество объектов, лучше всего использовать BufferDC.
Это так называемое Flicker-free drawing. Все сводиться к тому, что вы сначала рисуете в память BufferDC, а при завершении отрисовки вызывается деструктор BufferDC, в котором идет сброс картинки в физический CDC. В итоге ускоряется отрисовка и пропадает мерцание при частой отрисовке.

Будут вопросы, спрашивайте. Успехов:)

 Профиль  
                  
 
 
Сообщение29.04.2006, 19:24 
Аватара пользователя


18/02/06
61
Moscow
А последний вопрос у меня наполовину - алгоритмический - наполовину вот по этому пункту
Цитата:
4. В виде объявлено куча глобальных переменных (я говорю не про константы, а именно переменные Parts и прочее), которые используются в глобальных функциях. Если исключить глобальные функции, то эти данные хранят данные, которые были получены в результате обработки (т.е. в документе) и должны по идее храниться, создаваться и убаваться документом, т.е. быть его мемберами.

Я тут алгоритм (словесный) накидала. Я не очень поняла, какой из нижеследующих болков должен быть мембером какого:
(вернее, куда девать все переменных, чтобы памяти занимать поменьше, но чтобы все друг друга видели). И как мне организовать массив парных звезд в блоке 1, чтобы потом его эффективнее обрабатывать?
Вот, собственно, блоки:
Блок 1. Для N случайно выбранных точек из множества T создаем N звезд.
Вход: 2 массива точек типов 1 и 2.
Выход массив, элементами которого являются объекты CMyStar.
Работа: случайно выбираем тип точки, затем в соответствующем массиве случайно выбираем точку данного типа (следи за тем, чтобы не выбрать 1 точку дважды).
Заносим информацию о выбранной точке в объект CMyPoint. Ищем точки, удаленные от данной на расстояние, не большее d, заносим информацию о каждой выбранной точек в CMyPoint и вызываем CMyStar::AddConnection(центр, найденная точка). После того, как звезда построена, добавляем ее в массив.

Блок 2. Для каждой из N построенных звезд ищем пару в массиве точек M (массивы M и N независимы).
Вход: Массив объектов CMyStar и массив точек M.
Выход: Матрица результатов: первая строка – номер звезды из массива CMyStar, вторая строка – содержит указатель на звезду с центром из массива M, которая является парной данной (совпадающей с ней). Может быть так, что в массиве M найдется несколько звезд, парных к данной. Третья строка – число звезд, совпадающих с данной. 2 звезды являются совпадающими, если число точек в них отличается не больше, чем на k, а углы между каждыми двумя «лучами» отличаются не больше, чем на m.
Работа. Берем очередную звезду из CMyStar. Ищем в массиве M точку, тип которой совпадает с типом центра данной звезды. Строим звезду с центром в данной точке. Сравниваем 2 звезды. Если 2 звезды признаны совпадающими, добавляем информацию о построенной звезде в соответствующую позицию массива. Увеличиваем счетчик совпадающих звезд. Если нет – удаляем звезду, помечая ее центр, как «просмотренный».

Блок 3. Подсчитываем отношение (число совпавших звезд N1)/(число построенных звезд N).
Если оно больше некоторого порога t, то делаем вывод, что массивы M и T совпадают.
Для дополнительной проверки берем 1 звезду из массива T и 1 звезду из массива M (у которых найдена ровно 1 пара). Строим 2 звезды, центрами которых будут центры выбранных звезд, а концами лучей – центры оставшихся невыбранными звезд.
Если эти 2 звезды совпадают, то делаем окончательный вывод о совпадении двух множеств.

Блок 4 (дополнительный) – если у каких-либо звезд найдено больше одной пары, то найти пару, приближающую данную звезду наилучшим образом.
[/b]

 Профиль  
                  
 
 
Сообщение29.04.2006, 19:57 
Аватара пользователя


18/02/06
61
Moscow
И еще вот по поводу блока 2. Как лучше организовать сравнение двух звезд, для которых заданы помимо заданных тобой еще 2 мембера:
*число точек в звезде
*число точек каждого вида

Я вот что придумала: звезда-то у нас задана как набор соединений, созданных с помощью AddConnection. А чтобы 2 звезды сравнить, надо их развернуть таким образом, чтобы у них угол наклона относительно оси х совпадал (короче говоря, чтобы сравнить 2 циферблата часов, нужно второй развернуть так, чтобы цифра 12 была под таким же углом, как и у первого циферблата).
Так вот: я записываю все точки (кроме центральной), входящие в звезду, в виде массива CMyPoint'ов. Для второй звезды делаю то же.
Сравниваю первые элементы. если их типы совпадают, а длины отличаются не больше, чем на некоторую заданную величину, то сравниваю вторые элементы. если они не совпадают (может быть такое, что во второй звезде меньше точек, чем в первой где-то на 1-2 точки), то сравниваю третий элемент звезды, где больше точек с 2ым элементом звезды, где меньше точек (чтобы компенсировать пропуск). Если и эти элементы не совпадают, то я сдвигаю элементы в массиве 2, пока опять не будет выполнено условие "типы первых элементов совпадают" и повторяю все заново.

Как ты думаешь, алгоритм достаточно адекватен?

 Профиль  
                  
 
 
Сообщение03.05.2006, 16:48 


13/09/05
153
Москва
С учетом того, что Вы написали -
можно немного изменить структуру данных -
1. CMyStar - так нужны проверки на угол и на расстояние от центра, можно сформировать вектор точек, окружающих звезду, и упорядоченный по возрастанию угла.
2. Далее - в проверке есть такое условие - "длины отличаются не больше, чем на некоторую заданную величину" - и если эта DELTA намного меньше среднего расстояния между узлами и центром, то можно в CMyConnection добавить поле double m_dLength. Затем, в CMyStar добаляем код в часть добавления узлов - который подсчитывает мин. радиус и маскимальный радиус звезды, то есть минимум и максимум m_dLength добавляемых CMyConnection.
Таким образом, для звезд получаем две окружности, в которых лежат все точки - то есть некоторый регион, ограниченный этими окружностями.

Если центры двух звезд совпадают с учетом DELTA, число точек почти равно, плюс вопадение типов и т.д., и если регионы двух звезд пересекаются с учетом этой DELTA [(min1 - DELTA < max2 && min2 - DELTA < max1) или, если min1 и min2 <<max1> (max(max1, max2) - min(max1, max2) < 2*DELTA], то делаем остальные проверки на совпадение звезд.
Затем - упорядочиваем вектора узлов звезд по убыванию (возрастанию) расстояний до центра. Принимаем первые их элементы за "12 часов" и делаем проверки на углы. С первыми элементами не прошло, берем вторые, и так далее.

Тогда в CMyStar следует добавить два вектора - в первом узлы упорядочены по возрастанию углов, во втором - по убыванию (возрастанию) расстояний до центра + поле double m_dLength в CMyConnection.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 29 ]  На страницу Пред.  1, 2

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group