dtriangulationView.cpp
上传用户:chinasdcnc
上传日期:2022-07-02
资源大小:2702k
文件大小:28k
源码类别:

分形几何

开发平台:

Visual C++

  1. // dtriangulationView.cpp : CdtriangulationView 类的实现
  2. //
  3. #include "stdafx.h"
  4. #include "dtriangulation.h"
  5. #include "dcel.h"
  6. #include "dtriangulationDoc.h"
  7. #include "dtriangulationView.h"
  8. #include "GenPoints.h"
  9. #include "utility.h"
  10. #include <vector>
  11. #include "base.h"
  12. #include <stdlib.h>
  13. #include <time.h>
  14. #include <gl/GL.h>
  15. #include <gl/GLU.h>
  16. using namespace std;
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #endif
  20. #define MAXMANINPUTPOINTS 1000
  21. // CdtriangulationView
  22. IMPLEMENT_DYNCREATE(CdtriangulationView, CView)
  23. BEGIN_MESSAGE_MAP(CdtriangulationView, CView)
  24. // 标准打印命令
  25. ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
  26. ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
  27. ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
  28.     ON_COMMAND(ID_GENERATEPOINTS, &CdtriangulationView::OnGeneratePoints)
  29.     ON_COMMAND(ID_INPUTPOINTS, &CdtriangulationView::OnInputPoints)
  30.     ON_WM_LBUTTONDOWN()
  31.     ON_COMMAND(ID_TRIANGULATION, &CdtriangulationView::OnTriangulation)
  32.     ON_COMMAND(ID_FILE_NEW, &CdtriangulationView::OnFileNew)
  33.     ON_COMMAND(ID_FILE_OPEN, &CdtriangulationView::OnFileOpen)
  34.     ON_COMMAND(ID_FILE_SAVE, &CdtriangulationView::OnFileSave)
  35. ON_WM_KEYDOWN()
  36.     ON_WM_CREATE()
  37.     ON_WM_DESTROY()
  38.     ON_WM_ERASEBKGND()
  39.     ON_WM_SIZE()
  40. ON_WM_LBUTTONUP()
  41.     ON_COMMAND(ID_DCEL_TEST, &CdtriangulationView::OnDcelTest)
  42. ON_COMMAND(ID_CIRCLE_TEST, &CdtriangulationView::OnCircleTest)
  43.     ON_WM_MOUSEMOVE()
  44.     ON_COMMAND(ID_SHOW_ENLARGE, &CdtriangulationView::OnShowEnlarge)
  45.     ON_COMMAND(ID_SHOW_REVERT, &CdtriangulationView::OnShowRevert)
  46.     ON_WM_TIMER()
  47. ON_COMMAND(ID_DT_DEMO, &CdtriangulationView::OnDtDemo)
  48. END_MESSAGE_MAP()
  49. // CdtriangulationView 构造/析构
  50. CdtriangulationView::CdtriangulationView()
  51. {
  52.     isManInputState = false;
  53.     isLButtonDown = false;
  54.     isTest = false;
  55. isCircleTest = false;
  56.     isEnLarge = true;
  57.     isOne = false;
  58.     isPro = false;
  59. isDTDemo = false;
  60. circleTri = NULL;
  61. }
  62. CdtriangulationView::~CdtriangulationView()
  63. {
  64.     testTris.clear();
  65. }
  66. BOOL CdtriangulationView::PreCreateWindow(CREATESTRUCT& cs)
  67. {
  68. //  CREATESTRUCT cs 来修改窗口类或样式
  69. return CView::PreCreateWindow(cs);
  70. }
  71. // CdtriangulationView 绘制
  72. void CdtriangulationView::OnDraw(CDC* pDC)
  73. {
  74. CdtriangulationDoc* pDoc = GetDocument();
  75. ASSERT_VALID(pDoc);
  76. if (!pDoc)
  77. return;
  78. wglMakeCurrent(pDC->m_hDC, m_hRC);
  79.     glClearColor(1.0, 1.0, 1.0, 1.0);
  80.     glClear(GL_COLOR_BUFFER_BIT);
  81.     glMatrixMode(GL_MODELVIEW);
  82.     glLoadIdentity();
  83. // draw points
  84.     glColor4f(1.0, 0.0, 0.0, 1.0);
  85.     glPointSize(3.0f);
  86.     glBegin(GL_POINTS);
  87. for(int i = 0; i < pDoc->nPoints; ++i)
  88.         glVertex2d(pDoc->point(i)->x, pDoc->point(i)->y);
  89.     glEnd();
  90.     // draw lines
  91. if(pDoc->myDT.isFinished)
  92. {
  93. drawDT(pDoc->myDT.maxEdge.le);
  94. drawDT(pDoc->myDT.maxEdge.re);
  95. resetVisitedState(pDoc->myDT.maxEdge.le);
  96. resetVisitedState(pDoc->myDT.maxEdge.re);
  97. }
  98. // draw dt demo
  99. if(isDTDemo)
  100. {
  101. std::vector<MaxEdge>::iterator iter;
  102. //while(!maxEdges.empty())
  103. //{
  104. for(iter = maxEdges.begin(); iter != maxEdges.end(); iter++)
  105. {
  106. drawDT((*iter).le);
  107. drawDT((*iter).re);
  108. resetVisitedState((*iter).le);
  109. resetVisitedState((*iter).re);
  110. }
  111.     
  112. //}
  113. }
  114. // draw circle test
  115. if (isCircleTest && circleTri != NULL)
  116. {
  117.     GLUquadric* qd = gluNewQuadric();
  118.     glColor4f(0.4f, 0.0f, 1.0f, 0.4f);
  119.     gluQuadricDrawStyle(qd, GLU_FILL);
  120.     glPushMatrix();
  121.     glTranslated(cirTestCenter.x, cirTestCenter.y, 0.0);
  122.     gluDisk(qd, 0.0, cirTestRadius, 50, 4);
  123.     glPopMatrix();
  124.     gluDeleteQuadric(qd);
  125. }
  126.     // draw DCEL test
  127.     if(testTris.size() > 0 && isTest)
  128.     {
  129.         // draw tris
  130.         Point2d ps[3];
  131.         vector<Edge *>::iterator iter;
  132.         Edge *initEdge, *circleEdge;
  133.         int i;
  134.         glColor4f(0.0, 1.0f, 0.0, 0.3f);
  135.         glBegin(GL_TRIANGLES);
  136.         if (!isPro)
  137.         {
  138.             for(iter = testTris.begin(); iter != testTris.end(); ++iter)
  139.             {
  140.                 initEdge = *iter;
  141.                 circleEdge = initEdge;
  142.                 i = 0;
  143.                 do
  144.                 {
  145.                     ps[i].x = circleEdge->org2d().x;
  146.                     ps[i].y = circleEdge->org2d().y;
  147.                     ++i;
  148.                     circleEdge = circleEdge->lNext();
  149.                 }while(circleEdge != initEdge);
  150.                 glVertex2d(ps[0].x, ps[0].y);
  151.                 glVertex2d(ps[1].x, ps[1].y);
  152.                 glVertex2d(ps[2].x, ps[2].y);
  153.             }
  154.         }
  155.         else
  156.         {
  157.             int tmp = 0;
  158.             for(iter = testTris.begin(); iter != testTris.end(); ++iter)
  159.             {
  160.                 if (tmp++ > tempCount)
  161.                     break;
  162.                 initEdge = *iter;
  163.                 circleEdge = initEdge;
  164.                 i = 0;
  165.                 do
  166.                 {
  167.                     ps[i].x = circleEdge->org2d().x;
  168.                     ps[i].y = circleEdge->org2d().y;
  169.                     ++i;
  170.                     circleEdge = circleEdge->lNext();
  171.                 }while(circleEdge != initEdge);
  172.                 glVertex2d(ps[0].x, ps[0].y);
  173.                 glVertex2d(ps[1].x, ps[1].y);
  174.                 glVertex2d(ps[2].x, ps[2].y);
  175.             }
  176.         }
  177.         glEnd();
  178.     }
  179. if (isTest)
  180. {
  181.         // draw test line
  182.         glColor4f(1.0, 0.0, 1.0, 1.0);
  183.         glBegin(GL_LINES);
  184.         glVertex2d(startTestPoint.x, startTestPoint.y);
  185.         glVertex2d(finishTestPoint.x, finishTestPoint.y);
  186.         glEnd();
  187. }
  188.     if (isTest && isLButtonDown && isEnLarge)
  189.     {
  190.         // draw temp test line
  191.         glColor4f(1.0, 0.0, 1.0, 1.0);
  192.         glBegin(GL_LINES);
  193.         glVertex2d(startTestPoint.x, startTestPoint.y);
  194.         glVertex2d(tempTestPoint.x, tempTestPoint.y);
  195.         glEnd();
  196.     }
  197.     else if (isLButtonDown && !isEnLarge && isOne)
  198.     {
  199.         // draw rectangle
  200.         glColor4f(0.0f, 0.0, 1.0f, 0.4f);
  201.         glBegin(GL_QUADS);
  202.         glVertex2d(startRectPoint.x, startRectPoint.y);
  203.         glVertex2d(startRectPoint.x, tempRectPoint.y);
  204.         glVertex2d(tempRectPoint.x, tempRectPoint.y);
  205.         glVertex2d(tempRectPoint.x, startRectPoint.y);
  206.         glEnd();
  207.     }
  208.     glFlush();
  209.     SwapBuffers(pDC->m_hDC);
  210.     wglMakeCurrent(NULL, NULL);
  211. }
  212. // CdtriangulationView 打印
  213. BOOL CdtriangulationView::OnPreparePrinting(CPrintInfo* pInfo)
  214. {
  215. // 默认准备
  216. return DoPreparePrinting(pInfo);
  217. }
  218. void CdtriangulationView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  219. {
  220. // TODO: 添加额外的打印前进行的初始化过程
  221. }
  222. void CdtriangulationView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  223. {
  224. // TODO: 添加打印后进行的清除过程
  225. }
  226. void CdtriangulationView::resetVisitedState(Edge* e)
  227. {
  228.     DCEL *pDcel;
  229. Edge *edge;
  230. std::stack<Edge *>dcelStack;
  231. dcelStack.push(e);
  232. while(!dcelStack.empty())
  233. {
  234. edge = dcelStack.top();
  235. pDcel = (DCEL *)(edge->qEdge());
  236. dcelStack.pop();
  237.     if(pDcel->visited)
  238. {
  239. pDcel->visited = false;
  240.  
  241. dcelStack.push(edge->oNext());
  242. dcelStack.push(edge->oPrev());
  243. dcelStack.push(edge->dNext());
  244. dcelStack.push(edge->dPrev());
  245. }
  246. }
  247. }
  248. void CdtriangulationView::drawDT(Edge* e)
  249. {
  250.     CdtriangulationDoc* pDoc = GetDocument();
  251. DCEL *pDcel;
  252. Edge *edge;
  253. std::stack<Edge *>dcelStack;
  254. dcelStack.push(e);
  255.     glColor4f(0.0, 0.0, 0.0, 0.5);
  256.     glBegin(GL_LINES);
  257. while(!dcelStack.empty())
  258. {
  259. edge = dcelStack.top();
  260. pDcel = (DCEL *)(edge->qEdge());
  261. dcelStack.pop();
  262.     if(!pDcel->visited)
  263. {
  264.             glVertex2d(edge->org()->x, edge->org()->y);
  265.             glVertex2d(edge->dest()->x, edge->dest()->y);
  266. pDcel->visited = true;
  267. dcelStack.push(edge->oNext());
  268. dcelStack.push(edge->oPrev());
  269. dcelStack.push(edge->dNext());
  270. dcelStack.push(edge->dPrev());
  271. }
  272. }
  273.     glEnd();
  274. }
  275. // CdtriangulationView 诊断
  276. #ifdef _DEBUG
  277. void CdtriangulationView::AssertValid() const
  278. {
  279. CView::AssertValid();
  280. }
  281. void CdtriangulationView::Dump(CDumpContext& dc) const
  282. {
  283. CView::Dump(dc);
  284. }
  285. CdtriangulationDoc* CdtriangulationView::GetDocument() const // 非调试版本是内联的
  286. {
  287. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CdtriangulationDoc)));
  288. return (CdtriangulationDoc*)m_pDocument;
  289. }
  290. #endif //_DEBUG
  291. // CdtriangulationView 消息处理程序
  292. void CdtriangulationView::OnGeneratePoints(void)
  293. {
  294.     isManInputState = false;
  295.     isTest = false;
  296. isCircleTest = false;
  297.     CdtriangulationDoc* pDoc = GetDocument();
  298.     ASSERT_VALID(pDoc);
  299.     if (!pDoc)
  300.         return;
  301.     CGenPoints genPointDlg;
  302.     if (genPointDlg.DoModal() == IDOK)
  303.     {
  304.         pDoc->nPoints = genPointDlg.points;
  305.         if (pDoc->points != NULL)
  306.         {
  307.             pDoc->myDT.destroy();
  308.             delete[] pDoc->points;
  309.         }
  310.         testTris.clear();
  311.         pDoc->points = new Point2d[pDoc->nPoints];
  312.         CRect rect;
  313.         GetClientRect(&rect);
  314.         int maxHeight = rect.Height() - 5, maxWidth = rect.Width() - 5;
  315.         srand(unsigned(time(NULL)));
  316.         for (int i = 0; i < pDoc->nPoints; ++i)
  317.         {
  318.             double px = random(5, maxWidth) + random();
  319.             double py = random(5, maxHeight) + random();
  320.             pDoc->points[i].x = px;
  321.             pDoc->points[i].y = py;
  322.         }
  323.         Invalidate();
  324.     }
  325. }
  326. void CdtriangulationView::OnInputPoints(void)
  327. {
  328.     CdtriangulationDoc* pDoc = GetDocument();
  329.     ASSERT_VALID(pDoc);
  330.     if (!pDoc)
  331.         return;
  332.     if (!isEnLarge)
  333.         return;
  334.     pDoc->nPoints = 0;
  335.     testTris.clear();
  336.     if (pDoc->points != NULL)
  337.     {
  338.         pDoc->myDT.destroy();
  339.         delete[] pDoc->points;
  340.     }
  341.     pDoc->points = new Point2d[MAXMANINPUTPOINTS];
  342.     isManInputState = true;
  343.     isCircleTest = false;
  344.     isTest = false;
  345.     Invalidate();
  346. }
  347. void CdtriangulationView::OnTriangulation(void)
  348. {
  349. QueryPerformanceFrequency(&Freq);
  350.     isManInputState = false;
  351.     isCircleTest = false;
  352.     isTest = false;
  353.     CdtriangulationDoc* pDoc = GetDocument();
  354.     ASSERT_VALID(pDoc);
  355.     if (!pDoc)
  356.         return;
  357.     if (pDoc->nPoints <= 1)
  358.     {
  359.         MessageBox("Not enough points.", "warning");
  360.         return;
  361.     }
  362.     QueryPerformanceCounter(&BeginTime);
  363.     pDoc->myDT.initial(&(pDoc->nPoints), pDoc->points);
  364.     pDoc->myDT.doDelaunayTriangulation();
  365. QueryPerformanceCounter(&EndTime);
  366. // output runtime of delaunay triangulation.
  367. CString s;
  368. s.Format("三角剖分用时:%d us", (EndTime.QuadPart - BeginTime.QuadPart) * 1000000 / Freq.QuadPart);
  369. CStatusBar* pStatusBar = (CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
  370. pStatusBar->SetPaneText(pStatusBar->CommandToIndex(ID_INDICATOR_RUNTIME),s);
  371.     Invalidate();
  372. }
  373. void CdtriangulationView::OnFileNew(void)
  374. {
  375.     isManInputState = false;
  376.     isTest = false;
  377.     CdtriangulationDoc* pDoc = GetDocument();
  378.     ASSERT_VALID(pDoc);
  379.     if (!pDoc)
  380.         return;
  381.     pDoc->nPoints = 0;
  382.     pDoc->myDT.destroy();
  383.     delete[] pDoc->points;
  384.     testTris.clear();
  385.     pDoc->points = NULL;
  386.     CClientDC dc(this);
  387.     wglMakeCurrent(dc.m_hDC, m_hRC);
  388.     glMatrixMode(GL_PROJECTION);
  389.     glLoadIdentity();
  390.     CRect rect;
  391.     GetClientRect(&rect);
  392.     int maxHeight = rect.Height(), maxWidth = rect.Width();
  393.     gluOrtho2D(0, (double)maxWidth, (double)maxHeight, 0);
  394.     glViewport(0, 0, maxWidth, maxHeight);
  395.     wglMakeCurrent(NULL, NULL);
  396.     isEnLarge = true;
  397.     isCircleTest = false;
  398.     isOne = false;
  399.     Invalidate();
  400. }
  401. void CdtriangulationView::OnFileOpen(void)
  402. {
  403.     CFileDialog pCFileDialog(true, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
  404.                              TEXT("POINT files (*.point)|*.point|ALL files (*.*)|*.*||"), NULL);
  405.     pCFileDialog.m_ofn.lpstrTitle = TEXT("Open point file");
  406.     USES_CONVERSION;
  407.     if (pCFileDialog.DoModal() == IDOK)
  408.     {
  409.         CString strPathName = pCFileDialog.GetPathName();
  410.         if (!GetDocument()->load(T2A(strPathName.GetBuffer(strPathName.GetLength()))))
  411.         {
  412.             MessageBox(TEXT("Failing to open this file."), TEXT("Warning"));
  413.         }
  414.     }
  415.     isCircleTest = false;
  416.     isTest = false;
  417.     Invalidate();
  418. }
  419. void CdtriangulationView::OnFileSave(void)
  420. {
  421.     CFileDialog pCFileDialog(false, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
  422.                              TEXT("POINT files (*.point)|*.point|ALL files (*.*)|*.*||"), NULL);
  423.     pCFileDialog.m_ofn.lpstrTitle = TEXT("Save points file");
  424.     USES_CONVERSION;
  425.     if (pCFileDialog.DoModal() == IDOK)
  426.     {
  427.         CString strPathName = pCFileDialog.GetPathName();
  428.         if (!GetDocument()->save(T2A(strPathName.GetBuffer(strPathName.GetLength()))))
  429.         {
  430.             MessageBox(TEXT("Failing to save this file."), TEXT("Warning"));
  431.         }
  432.     }
  433.     isCircleTest = false;
  434.     isTest = false;
  435.     Invalidate();
  436. }
  437. void CdtriangulationView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  438. {
  439. // TODO: 在此添加消息处理程序代码和/或调用默认值
  440.     isTest = false;
  441.     testTris.clear();
  442.     if(0x0d == nChar)
  443. {
  444. isCircleTest = false;
  445.     CdtriangulationDoc* pDoc = GetDocument();
  446. ASSERT_VALID(pDoc);
  447. if (!pDoc)
  448. return;
  449. if (pDoc->nPoints <= 1)
  450.     pDoc->nPoints = 100;
  451.         if (pDoc->points != NULL)
  452.         {
  453.             pDoc->myDT.destroy();
  454.             delete[] pDoc->points;
  455.         }
  456.         pDoc->points = new Point2d[pDoc->nPoints];
  457.         CRect rect;
  458.         GetClientRect(&rect);
  459.         int maxHeight = rect.Height() - 5, maxWidth = rect.Width() - 5;
  460.         srand(unsigned(time(NULL)));
  461.         for (int i = 0; i < pDoc->nPoints; ++i)
  462.         {
  463.             double px = random(5, maxWidth) + random();
  464.             double py = random(5, maxHeight) + random();
  465.             pDoc->points[i].x = px;
  466.             pDoc->points[i].y = py;
  467.         }
  468.         QueryPerformanceFrequency(&Freq);
  469.         QueryPerformanceCounter(&BeginTime);
  470.         pDoc->myDT.initial(&(pDoc->nPoints), pDoc->points);
  471.         pDoc->myDT.doDelaunayTriangulation();
  472.         QueryPerformanceCounter(&EndTime);
  473.         // output runtime of delaunay triangulation.
  474.         CString s;
  475.         s.Format("%d us", (EndTime.QuadPart - BeginTime.QuadPart) * 1000000 / Freq.QuadPart);
  476.         CStatusBar* pStatusBar = (CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
  477.         pStatusBar->SetPaneText(pStatusBar->CommandToIndex(ID_INDICATOR_RUNTIME),s);
  478.         Invalidate();
  479. }
  480. CView::OnKeyDown(nChar, nRepCnt, nFlags);
  481. }
  482. int CdtriangulationView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  483. {
  484.     if (CView::OnCreate(lpCreateStruct) == -1)
  485.         return -1;
  486.     CClientDC dc(this);
  487.     PIXELFORMATDESCRIPTOR pdf;
  488.     memset(&pdf, 0, sizeof(PIXELFORMATDESCRIPTOR));
  489.     pdf.nSize = sizeof(PIXELFORMATDESCRIPTOR);
  490.     pdf.nVersion = 1;
  491.     pdf.dwFlags = PFD_DRAW_TO_WINDOW |
  492.                   PFD_SUPPORT_OPENGL |
  493.                   PFD_DOUBLEBUFFER;
  494.     pdf.iPixelType = PFD_TYPE_RGBA;
  495.     pdf.cColorBits = 24;
  496.     pdf.cDepthBits = 32;
  497.     int pixelFormat = ChoosePixelFormat(dc.m_hDC, &pdf);
  498.     SetPixelFormat(dc.m_hDC, pixelFormat, &pdf);
  499.     m_hRC = wglCreateContext(dc.m_hDC);
  500.     return 0;
  501. }
  502. void CdtriangulationView::OnDestroy()
  503. {
  504.     CView::OnDestroy();
  505.     wglMakeCurrent(NULL, NULL);
  506.     wglDeleteContext(m_hRC);
  507.     m_hRC = NULL;
  508. }
  509. BOOL CdtriangulationView::OnEraseBkgnd(CDC* pDC)
  510. {
  511.     //return CView::OnEraseBkgnd(pDC);
  512.     return true;
  513. }
  514. void CdtriangulationView::OnSize(UINT nType, int cx, int cy)
  515. {
  516.     CView::OnSize(nType, cx, cy);
  517.     CClientDC dc(this);
  518.     wglMakeCurrent(dc.m_hDC, m_hRC);
  519.     glMatrixMode(GL_PROJECTION);
  520.     glLoadIdentity();
  521.     glEnable(GL_LINE_SMOOTH);
  522.     glEnable(GL_BLEND);
  523.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  524.     glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
  525.     CRect rect;
  526.     GetClientRect(&rect);
  527.     int maxHeight = rect.Height(), maxWidth = rect.Width();
  528.     gluOrtho2D(0, (double)maxWidth, (double)maxHeight, 0);
  529.     glViewport(0, 0, cx, cy);
  530.     wglMakeCurrent(NULL, NULL);
  531. }
  532. void CdtriangulationView::OnLButtonDown(UINT nFlags, CPoint point)
  533. {
  534.     CdtriangulationDoc* pDoc = GetDocument();
  535.     ASSERT_VALID(pDoc);
  536.     if (!pDoc)
  537.         return;
  538.     if (isManInputState)
  539.     {
  540.         if (pDoc->nPoints >= MAXMANINPUTPOINTS)
  541.         {
  542.             MessageBox("Too many input points!", "warning");
  543.         }
  544.         else
  545.         {
  546.             Point2d tp(point.x, point.y);
  547.             pDoc->points[pDoc->nPoints++] = tp;
  548.             Invalidate();
  549.         }
  550.     }
  551.     else if (!isEnLarge)
  552.     {
  553.         startRectPoint.x = point.x;
  554.         startRectPoint.y = point.y;
  555.         isLButtonDown = true;
  556.     }
  557. else if (isTest)
  558. {
  559. testTris.clear();
  560.     startTestPoint.x = point.x;
  561. startTestPoint.y = point.y;
  562.         finishTestPoint.x = point.x;
  563.     finishTestPoint.y = point.y;
  564.         isLButtonDown = true;
  565. }
  566. else if (isCircleTest)
  567. {
  568.     if(pDoc->myDT.isFinished)
  569.     {
  570. circleTri = locate(Point2d(point.x, point.y), pDoc->myDT.maxEdge.le);
  571.     if (circleTri != NULL)
  572. {
  573. circumCircle(circleTri->org2d(), circleTri->next()->org2d(),
  574.          circleTri->next()->dest2d(), &cirTestCenter,
  575.  &cirTestRadius);
  576. Invalidate();
  577. }
  578.     }
  579. }
  580.     CView::OnLButtonDown(nFlags, point);
  581. }
  582. void CdtriangulationView::OnLButtonUp(UINT nFlags, CPoint point)
  583. {
  584. // TODO: 在此添加消息处理程序代码和/或调用默认值
  585.     if (isTest && isEnLarge)
  586.     {
  587.         finishTestPoint.x = point.x;
  588.     finishTestPoint.y = point.y;
  589.     
  590.     CdtriangulationDoc* pDoc = GetDocument();
  591.     ASSERT_VALID(pDoc);
  592.     if(pDoc->myDT.isFinished)
  593.     {
  594.     intersectedTris(startTestPoint, finishTestPoint, testTris, pDoc->myDT.maxEdge.le);
  595.             isPro = true;
  596.             int detal = 100;
  597.             if (pDoc->nPoints > 500)
  598.                 detal = 50;
  599.             else if (pDoc->nPoints > 5000)
  600.                 detal = 10;
  601.             m_nTimer = SetTimer(1, detal, 0);
  602.             tempCount = -1;
  603.     Invalidate();
  604.     }
  605.     }
  606.     else if (isOne && !isEnLarge)
  607.     {
  608.         endRectPoint.x = point.x;
  609.         endRectPoint.y = point.y;
  610.         CClientDC dc(this);
  611.         wglMakeCurrent(dc.m_hDC, m_hRC);
  612.         glMatrixMode(GL_PROJECTION);
  613.         glLoadIdentity();
  614.         CRect rect;
  615.         GetClientRect(&rect);
  616.         int maxHeight = rect.Height(), maxWidth = rect.Width();
  617.         double maxw = getMax(startRectPoint.x, endRectPoint.x);
  618.         double minw = getMin(startRectPoint.x, endRectPoint.x);
  619.         double maxh = getMax(startRectPoint.y, endRectPoint.y);
  620.         double minh = getMin(startRectPoint.y, endRectPoint.y);
  621.         gluOrtho2D(getMax(minw, 1.0), getMax(maxw, 1.0), getMax(maxh, 1.0), getMax(minh, 1.0));
  622.         glViewport(0, 0, maxWidth, maxHeight);
  623.         wglMakeCurrent(NULL, NULL);
  624.         isOne = false;
  625.         Invalidate();
  626.     }
  627.     isLButtonDown = false;
  628. CView::OnLButtonUp(nFlags, point);
  629. }
  630. void CdtriangulationView::OnDcelTest(void)
  631. {
  632.     if (GetDocument()->nPoints <= 1 || !GetDocument()->myDT.isFinished || !isEnLarge)
  633.     {
  634.         MessageBox("Can not do DCEL test!", "warning");
  635.         Invalidate();
  636.         return;
  637.     }
  638.     isTest = true;
  639.     isManInputState = false;
  640. isCircleTest = false;
  641.     tempCount = -1;
  642. }
  643. void CdtriangulationView::OnCircleTest(void)
  644. {
  645.     if (GetDocument()->nPoints <= 2 || !GetDocument()->myDT.isFinished || !isEnLarge) // delete !isEnlarge
  646.     {
  647.         MessageBox("Can not do circle test!", "warning");
  648.         Invalidate();
  649.         return;
  650.     }
  651. isCircleTest = true;
  652.     isTest = false;
  653.     isManInputState = false;
  654. }
  655. void CdtriangulationView::OnMouseMove(UINT nFlags, CPoint point)
  656. {
  657.     CdtriangulationDoc* pDoc = GetDocument();
  658.     ASSERT_VALID(pDoc);
  659.     if (isLButtonDown && !isEnLarge && isOne)
  660.     {
  661.         tempRectPoint.x = point.x;
  662.         tempRectPoint.y = point.y;
  663.         Invalidate();
  664.     }
  665.     if ((pDoc->myDT.isFinished && isTest && isLButtonDown))
  666.     {
  667.         tempTestPoint.x = point.x;
  668.         tempTestPoint.y = point.y;
  669.         Invalidate();
  670.     }
  671.     CView::OnMouseMove(nFlags, point);
  672. }
  673. void CdtriangulationView::OnShowEnlarge(void)
  674. {
  675.     if (isEnLarge)
  676.     {
  677.         isEnLarge = false;
  678.         isOne = true;
  679.         isManInputState = false;
  680.         CString s = "放大状态,不能进行其他操作";
  681.         CStatusBar* pStatusBar = (CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
  682.         pStatusBar->SetPaneText(pStatusBar->CommandToIndex(ID_INDICATOR_RUNTIME),s);
  683.     }
  684. }
  685. void CdtriangulationView::OnShowRevert(void)
  686. {
  687.     if (!isEnLarge)
  688.     {
  689.         CClientDC dc(this);
  690.         wglMakeCurrent(dc.m_hDC, m_hRC);
  691.         glMatrixMode(GL_PROJECTION);
  692.         glLoadIdentity();
  693.         CRect rect;
  694.         GetClientRect(&rect);
  695.         int maxHeight = rect.Height(), maxWidth = rect.Width();
  696.         gluOrtho2D(0, (double)maxWidth, (double)maxHeight, 0);
  697.         glViewport(0, 0, maxWidth, maxHeight);
  698.         wglMakeCurrent(NULL, NULL);
  699.         isEnLarge = true;
  700.         isOne = false;
  701.         CString s = "视图状态恢复正常";
  702.         CStatusBar* pStatusBar = (CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
  703.         pStatusBar->SetPaneText(pStatusBar->CommandToIndex(ID_INDICATOR_RUNTIME),s);
  704.         Invalidate();
  705.     }
  706. }
  707. void CdtriangulationView::OnTimer(UINT_PTR nIDEvent)
  708. {
  709.     if (nIDEvent == m_nTimer)
  710.     {
  711.         if (tempCount == testTris.size())
  712.         {
  713.             KillTimer(m_nTimer);
  714.             isPro = false;
  715.         }
  716.         else
  717.         {
  718.             ++tempCount;
  719.         }
  720.         Invalidate();
  721.     }
  722.     CView::OnTimer(nIDEvent);
  723. }
  724. void CdtriangulationView::OnDtDemo()
  725. {
  726. // TODO: 在此添加命令处理程序代码
  727.     CdtriangulationDoc* pDoc = GetDocument();
  728.     ASSERT_VALID(pDoc);
  729.     if (!pDoc)
  730.         return;
  731.     if (pDoc->nPoints <= 1)
  732.         return;
  733. this->isTest = false;
  734. this->isCircleTest = false;
  735. this->isManInputState = false;
  736. this->isDTDemo = true;
  737.     if (pDoc->myDT.nPoints >= 100000)
  738.     {
  739.         MessageBox("too many points!", "warning");
  740.         return;
  741.     }
  742. while(!maxEdges.empty())
  743. {
  744. maxEdges.clear();
  745. }
  746.    
  747.     pDoc->myDT.initial(&(pDoc->nPoints), pDoc->points);
  748.     if (pDoc->myDT.nPoints >= 2)
  749.     {
  750. pDoc->myDT.maxEdge = delaunayDemo(0, pDoc->myDT.nPoints - 1, 1000 / pDoc->nPoints);
  751.         pDoc->myDT.isFinished = true;
  752.     }
  753. this->isDTDemo = false;
  754. }
  755. MaxEdge CdtriangulationView::delaunayDemo(int begin, int end, int timeInterval)
  756. {
  757.     // the number of points
  758.     int size = end - begin + 1;
  759.     // max edge
  760.     MaxEdge ret;
  761. // doc
  762. CdtriangulationDoc* pDoc = GetDocument();
  763.     ASSERT_VALID(pDoc);
  764.     // delaunay triangulation
  765.     if(size == 2) // only two points
  766.     {
  767.         // let s1, s2 be two sites in sorted order.
  768.         // create an edge a from s1 to s2
  769.         Edge* a = makeEdge();
  770. a->endPoints(pDoc->myDT.point(begin), pDoc->myDT.point(end));
  771.         ret.le = a;
  772.         ret.re = a->twin();
  773. maxEdges.insert(maxEdges.end(), ret);
  774. // demo
  775. Sleep(timeInterval);
  776. pDoc->myDT.maxEdge = ret;
  777. OnDraw(GetDC());
  778.         return ret;
  779.     }
  780.     else if(size == 3) // only three points
  781.     {
  782.         // let s1, s2, s3 be the three sites, in sorted order,
  783.         // create edges a connecting s1 to s2 and b connecting s2 to s3
  784.         Edge* a = makeEdge();
  785.         Edge* b = makeEdge();
  786.         splice(a->twin(), b);
  787.         a->endPoints(pDoc->myDT.point(begin), pDoc->myDT.point(begin + 1));
  788.         b->endPoints(pDoc->myDT.point(begin + 1), pDoc->myDT.point(end));
  789.         // close the triangle
  790.         Edge* c;
  791.         if(ccw(*pDoc->myDT.point(begin), *pDoc->myDT.point(begin + 1), *pDoc->myDT.point(end)))
  792.         {
  793.             c = connect(b, a);
  794.             ret.le = a;
  795.             ret.re = b->twin();
  796.         }
  797.         else if(ccw(*pDoc->myDT.point(begin), *pDoc->myDT.point(end), *pDoc->myDT.point(begin + 1)))
  798.         {
  799.             c = connect(b, a);
  800.             ret.le = c->twin();
  801.             ret.re = c;
  802.         }
  803.         else  // the three points are collinear
  804.         {
  805.             ret.le = a;
  806.             ret.re = b->twin();
  807.         }
  808. maxEdges.insert(maxEdges.end(), ret);
  809. // demo
  810. Sleep(timeInterval);
  811. pDoc->myDT.maxEdge = ret;
  812. OnDraw(GetDC());
  813.         return ret;
  814.     }
  815.     else // |sites| >= 4
  816.     {
  817.         Edge *ldo, *ldi; // left half result
  818.         Edge *rdo, *rdi; // right half result
  819.         // recursively delaunay triangulation L and R halves
  820.         MaxEdge leftRet = delaunayDemo(begin, begin + (size / 2) - 1, timeInterval);
  821.         MaxEdge rightRet = delaunayDemo(begin + (size / 2), end, timeInterval);
  822.         ldo = leftRet.le;
  823.         ldi = leftRet.re;
  824.         rdi = rightRet.le;
  825.         rdo = rightRet.re;
  826.         // Compute the lower commom tangent of L and R
  827.         while(1)
  828.         {
  829.             if(leftOf(*(rdi->org()), ldi))
  830.             {
  831.                 ldi = ldi->lNext();
  832.             }
  833.             else if(rightOf(*(ldi->org()), rdi))
  834.             {
  835.                 rdi = rdi->rPrev();
  836.             }
  837.             else
  838.             {
  839.                 break;
  840.             }
  841.         }
  842.         // create a first edge basel from rdi.org to ldi.org
  843.         Edge* basel = connect(rdi->twin(), ldi);
  844.         if((ldi->org()) == (ldo->org()))
  845.         {
  846.             ldo = basel->twin();
  847.         }
  848.         if((rdi->org()) == (rdo->org()))
  849.         {
  850.             rdo = basel;
  851.         }
  852.         // merge
  853.         while(1)
  854.         {
  855.             // locate the first L point (lcand.Dest) to be encountered by the rising bubble
  856.             // and delete L edges out of basel.Dest that fail the circle test
  857.             Edge* lcand = basel->twin()->oNext();
  858.             Edge* t;
  859.             if(valid(lcand, basel))
  860.             {
  861.                 while(inCircle(*(basel->dest()), *(basel->org()), *(lcand->dest()), 
  862.                                *(lcand->oNext()->dest())))
  863.                 {
  864.                     t = lcand->oNext();
  865.                     deleteEdge(lcand);
  866.                     lcand = t;
  867.                 }
  868.             }
  869.             // symmetrically, locate the first R point to be hit, and delete R edges
  870.             Edge* rcand = basel->oPrev();
  871.             if(valid(rcand, basel))
  872.             {
  873.                 while(inCircle(*(basel->dest()), *(basel->org()), *(rcand->dest()), 
  874.                                *(rcand->oPrev()->dest())))
  875.                 {
  876.                     t = rcand->oPrev();
  877.                     deleteEdge(rcand);
  878.                     rcand = t;
  879.                 }
  880.             }
  881.             // if both lcand and rcand are invalid, then basel is the upper common tangent
  882.             if((!valid(lcand, basel)) && (!valid(rcand, basel)))
  883.             {
  884.                 break;
  885.             }
  886.             // the next cross edge is to be connected to either lcand.Dest or rcand.Dest
  887.             // if both are valid, then choose the appropriate one using the inCircle test
  888.             if((!valid(lcand, basel)) || (valid(rcand, basel)
  889.                     && inCircle(*(lcand->dest()), *(lcand->org()),
  890.                                 *(rcand->org()), *(rcand->dest()))))
  891.             {
  892.                 // add cross edge basel from rcand.Dest to basel.Dest
  893.                 basel = connect(rcand, basel->twin());
  894.             }
  895.             else
  896.             {
  897.                 // add cross edge basel from basel.org to lcand.Dest
  898.                 basel = connect(basel->twin(), lcand->twin());
  899.             }
  900.         }
  901.         ret.le = ldo;
  902.         ret.re = rdo;
  903. maxEdges.erase(maxEdges.end() - 1);
  904. maxEdges.erase(maxEdges.end() - 1);
  905. maxEdges.insert(maxEdges.end(), ret);
  906. // demo
  907. Sleep(timeInterval);
  908. pDoc->myDT.maxEdge = ret;
  909. OnDraw(GetDC());
  910.         return ret;
  911.     }
  912. }