www.pudn.com > CurveEditor.rar > CurveEditorView.cpp


// CurveEditorView.cpp : implementation of the CCurveEditorView class 
// 
 
#include "stdafx.h" 
#include "CurveEditor.h" 
 
#include "CurveEditorDoc.h" 
#include "CurveEditorView.h" 
#include  
#include "UIStructure.h" 
#include "MainFrm.h" 
 
#include "Helper.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CCurveEditorView 
 
IMPLEMENT_DYNCREATE(CCurveEditorView, CView) 
 
BEGIN_MESSAGE_MAP(CCurveEditorView, CView) 
	//{{AFX_MSG_MAP(CCurveEditorView) 
	ON_WM_SIZE() 
	ON_WM_LBUTTONUP() 
	ON_WM_LBUTTONDOWN() 
	ON_WM_SETCURSOR() 
	ON_WM_MOUSEMOVE() 
	ON_WM_KEYDOWN() 
	ON_WM_KEYUP() 
	ON_COMMAND(ID_ALWAYS_SHOW_SPLIT_POINT, OnAlwaysShowSplitPoint) 
	ON_UPDATE_COMMAND_UI(ID_ALWAYS_SHOW_SPLIT_POINT, OnUpdateAlwaysShowSplitPoint) 
	ON_COMMAND(ID_SHOW_TANGENT, OnShowTangent) 
	ON_UPDATE_COMMAND_UI(ID_SHOW_TANGENT, OnUpdateShowTangent) 
	ON_COMMAND(ID_NEW_CURVES, OnNewCurves) 
	ON_COMMAND(ID_MOVE_INTERSECTION, OnMoveIntersection) 
	ON_UPDATE_COMMAND_UI(ID_MOVE_INTERSECTION, OnUpdateMoveIntersection) 
	//}}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) 
	ON_MESSAGE(MFR_COMMAND, OnMainFrameCommand) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CCurveEditorView construction/destruction 
 
CCurveEditorView::CCurveEditorView() 
{ 
	// TODO: add construction code here 
	m_cxWnd = 0; 
	m_nCurrentPane = 0; 
	m_posPointCatched = NULL; 
	m_nCurrentCurve = -1; 
 
	m_rgb[0] = RGB(0,0,0); 
	m_rgb[1] = RGB(0,0,255); 
 
 
	alpha = 3.14/6; 
	theta = 3.14/2.5; 
 
	k=1.1; 
	kNormal=1.3; 
 
	m_bScale = false; 
	m_bRotate = false; 
	m_bDown = false; 
	m_bAlwaysShowInts = false; 
	m_bAlwaysSplitPoint =false; 
	m_bShowTangent = false; 
	m_bMoveIntersection = false; 
} 
 
CCurveEditorView::~CCurveEditorView() 
{ 
} 
 
BOOL CCurveEditorView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: Modify the Window class or styles here by modifying 
	//  the CREATESTRUCT cs 
 
	return CView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CCurveEditorView drawing 
 
void CCurveEditorView::OnDraw(CDC* pDC) 
{ 
	CCurveEditorDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
	// TODO: add draw code for native data here 
	pDC->BitBlt(0, 0, m_cxWnd, m_cyWnd, &m_dcMem, 0, 0, SRCCOPY); 
} 
///////////////////////////////////////////////////////////////////////////// 
// CCurveEditorView printing 
 
BOOL CCurveEditorView::OnPreparePrinting(CPrintInfo* pInfo) 
{ 
	// default preparation 
	return DoPreparePrinting(pInfo); 
} 
 
void CCurveEditorView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add extra initialization before printing 
} 
 
void CCurveEditorView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add cleanup after printing 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CCurveEditorView diagnostics 
 
#ifdef _DEBUG 
void CCurveEditorView::AssertValid() const 
{ 
	CView::AssertValid(); 
} 
 
void CCurveEditorView::Dump(CDumpContext& dc) const 
{ 
	CView::Dump(dc); 
} 
 
CCurveEditorDoc* CCurveEditorView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCurveEditorDoc))); 
	return (CCurveEditorDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CCurveEditorView message handlers 
 
void CCurveEditorView::OnInitialUpdate()  
{ 
	int i; 
	CRect rect; 
 
	CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd(); 
	CView::OnInitialUpdate(); 
 
	((CMainFrame*)::AfxGetMainWnd())->SetEditorViewHwnd(GetSafeHwnd()); 
	 
	CCurveEditorDoc* pDoc = GetDocument(); 
//	CCurveEditorDoc* pDoc = (CCurveEditorDoc*)GetDocument(); 
	pDoc->m_pObjectsTreeView = (CObjectsTree*)pFrame->GetTreeView(); 
	pDoc->AddView(pDoc->m_pObjectsTreeView); 
	pDoc->m_hWndObjects = pDoc->m_pObjectsTreeView->GetSafeHwnd(); 
 
	ASSERT_VALID(pDoc); 
	// get control pad hwnd 
	m_hWndObjects = pDoc->m_hWndObjects; 
 
	// Initialize the control points 
	VECTOR vCtrl1[4], vOffset={10, 10, 10}; 
 
	vCtrl1[0].x=0; 
	vCtrl1[0].y=0; 
	vCtrl1[0].z=0; 
	vCtrl1[1].x=-44; 
	vCtrl1[1].y=2; 
	vCtrl1[1].z=36; 
	vCtrl1[2].x=-120; 
	vCtrl1[2].y=0; 
	vCtrl1[2].z=67; 
	vCtrl1[3].x=34; 
	vCtrl1[3].y=-53; 
	vCtrl1[3].z=99; 
 
	for(i=0; i<4; i++) 
	{ 
		pDoc->m_alstCtrlPoint[0].AddTail(vCtrl1[i]); 
		pDoc->m_alstCtrlPoint[1].AddTail(vCtrl1[i]+vOffset); 
	} 
 
	// create off-screen buffer 
	pDoc->SetMainViewHwnd(GetSafeHwnd()); 
	CClientDC dc(this); 
	m_cxScr = GetSystemMetrics(SM_CXSCREEN); 
	m_cyScr = GetSystemMetrics(SM_CYSCREEN); 
	m_bmp.CreateCompatibleBitmap(&dc, m_cxScr, m_cyScr); 
	m_dcMem.CreateCompatibleDC(&dc); 
	m_pBmpOld = m_dcMem.SelectObject(&m_bmp); 
 
	DrawSplit(); 
	DrawCurve(); 
	DrawCube(); 
} 
 
void CCurveEditorView::DrawSplit() 
{ 
	m_dcMem.FillSolidRect(0, 0, m_cxScr, m_cxScr, RGB(230,230,255)); 
	 
	CPen pen(PS_SOLID, 0, RGB(255,255,255)), *pPenOld; 
	pPenOld = m_dcMem.SelectObject(&pen); 
 
	m_dcMem.MoveTo(0, m_cyWnd/2-2); 
	m_dcMem.LineTo(m_cxWnd, m_cyWnd/2-2); 
	m_dcMem.MoveTo(m_cxWnd/2-2, 0); 
	m_dcMem.LineTo(m_cxWnd/2-2, m_cyWnd); 
 
	m_dcMem.SelectObject(pPenOld); 
	pen.DeleteObject(); 
	pen.CreatePen(PS_SOLID, 0, RGB(90,90,90)); 
	pPenOld = m_dcMem.SelectObject(&pen); 
 
	m_dcMem.MoveTo(m_cxWnd/2+2, 0); 
	m_dcMem.LineTo(m_cxWnd/2+2, m_cyWnd); 
	m_dcMem.MoveTo(0, m_cyWnd/2+2); 
	m_dcMem.LineTo(m_cxWnd, m_cyWnd/2+2); 
 
	m_dcMem.SelectObject(pPenOld); 
	pen.DeleteObject(); 
	pen.CreatePen(PS_SOLID, 3, RGB(192,192,192)); 
	pPenOld = m_dcMem.SelectObject(&pen); 
 
	m_dcMem.MoveTo(0, m_cyWnd/2); 
	m_dcMem.LineTo(m_cxWnd, m_cyWnd/2); 
 
	m_dcMem.MoveTo(m_cxWnd/2, 0); 
	m_dcMem.LineTo(m_cxWnd/2, m_cyWnd); 
 
	m_dcMem.SelectObject(pPenOld); 
	pen.DeleteObject(); 
	pen.CreatePen(PS_SOLID, 0, RGB(0,0,255)); 
	pPenOld = m_dcMem.SelectObject(&pen); 
	 
	int x, y; 
	x=(m_nCurrentPane%2)*m_cxWnd/2; 
	y=(m_nCurrentPane/2)*m_cyWnd/2; 
	m_dcMem.MoveTo(x, y); 
	m_dcMem.LineTo(x+m_cxWnd/2, y); 
	m_dcMem.LineTo(x+m_cxWnd/2, y+m_cyWnd/2); 
	m_dcMem.LineTo(x, y+m_cyWnd/2); 
	m_dcMem.LineTo(x, y); 
 
	m_dcMem.SelectObject(pPenOld); 
	pen.DeleteObject(); 
} 
 
void CCurveEditorView::OnSize(UINT nType, int cx, int cy)  
{ 
	CView::OnSize(nType, cx, cy); 
	 
	// TODO: Add your message handler code here 
	m_cxWnd = cx; 
	m_cyWnd = cy; 
 
	m_rectFront.left = 0; m_rectFront.top = 0; 
	m_rectFront.right = m_cxWnd/2-2; 
	m_rectFront.bottom = m_cyWnd/2-2; 
 
	m_rectLeft.left = m_cxWnd/2+3; 
	m_rectLeft.bottom = m_cyWnd/2-2; 
	m_rectLeft.right = m_cxWnd; m_rectLeft.top = 0; 
 
	m_rectTop.left = 0; m_rectTop.bottom = m_cyWnd; 
	m_rectTop.top = m_cyWnd/2+3; 
	m_rectTop.right = m_cxWnd/2-2; 
 
	m_rectUser.right = m_cxWnd; m_rectUser.bottom = m_cyWnd; 
	m_rectUser.top = m_cyWnd/2+3; 
	m_rectUser.left = m_cxWnd/2+3; 
 
	if(m_dcMem.GetSafeHdc()) 
	{ 
		DrawSplit(); 
		DrawCurve(); 
		DrawCube(); 
	} 
} 
 
 
void CCurveEditorView::DrawCurve() 
{ 
	VECTOR vPoint[100]; 
	VECTOR* pvCtrlPoint; 
	int x0, y0, x1, y1; 
	int i, nCurveNum, count; 
 
	CCurveEditorDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
 
	POSITION position; 
	CPen pen, *pPenOld; 
	for(nCurveNum=0; nCurveNum<2; nCurveNum++) 
	{ 
		// prepare pen 
		pen.CreatePen(PS_SOLID, 0, m_rgb[nCurveNum]); 
		pPenOld = m_dcMem.SelectObject(&pen); 
 
		count = pDoc->m_alstCtrlPoint[nCurveNum].GetCount(); 
		pvCtrlPoint = new VECTOR[count]; 
		position = pDoc->m_alstCtrlPoint[nCurveNum].GetHeadPosition(); 
		for(i=0; im_alstCtrlPoint[nCurveNum].GetNext(position); 
		 
		// calculate curve 
		for(i=0; i<100; i++) 
			//Bezier(pvCtrlPoint1, &vPoint[i], 1.0/99*i); 
			DeCasteljau(pvCtrlPoint, count, 1.0/99*i, &vPoint[i]); 
 
		// Draw user view 
		VECTOR a; 
		VECTOR2D Pe; 
		a.x=0; a.y=0; a.z=10; 
		Pn.x = -sin(theta)*cos(alpha); 
		Pn.y = -sin(theta)*sin(alpha); 
		Pn.z = -cos(theta); 
		Px = a%((-1)*Pn); 
 
		x0 = (m_rectUser.left + m_rectUser.right)/2; 
		y0 = (m_rectUser.top + m_rectUser.bottom)/2; 
		Pe = k*ProjectParallel(vPoint[0], Pn, Px); 
		m_dcMem.MoveTo(x0 + (int)Pe.x, y0 - (int)Pe.y); 
		for(i=1; i<100; i++) 
		{ 
			Pe = k*ProjectParallel(vPoint[i], Pn, Px); 
			m_dcMem.LineTo(x0 + (int)Pe.x, y0 - (int)Pe.y); 
		} 
 
		for(i=0; i<100; i++) 
			vPoint[i] = kNormal*vPoint[i]; 
 
		// Draw other view 
		x0 = (m_rectFront.left + m_rectFront.right)/2; 
		y0 = (m_rectFront.top + m_rectFront.bottom)/2; 
		m_dcMem.MoveTo((int)(x0+vPoint[0].y), (int)(y0-vPoint[0].z)); 
		for(i=1; i<100; i++) 
			m_dcMem.LineTo((int)(x0+vPoint[i].y), (int)(y0-vPoint[i].z)); 
		if(m_nCurrentPane == 0) 
			for(i=0; i *plstCtrlPoint; 
	VECTOR *pvPoint, *pvCtrl; 
	POSITION position; 
	CCurveEditorDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
 
	plstCtrlPoint = pDoc->m_alstCtrlPoint; 
	for(nCurve=0; nCurve<2; nCurve++) 
	{ 
		n = plstCtrlPoint[nCurve].GetCount(); 
		pT = new double[3*n]; 
		pvCtrl = new VECTOR[3*n]; 
		pvPoint = new VECTOR[3*n]; 
		// fill control point array 
		position = plstCtrlPoint[nCurve].GetHeadPosition(); 
		for(i=0; im_alstCtrlPoint[nCurveNum].GetHeadPosition(); 
			m_posPointCatched = NULL; 
			if(m_nCurrentPane == 0) 
			{ 
				x0 = (m_rectFront.left + m_rectFront.right)/2; 
				y0 = (m_rectFront.top + m_rectFront.bottom)/2; 
				do{ 
					posOld = position; 
					vector = pDoc->m_alstCtrlPoint[nCurveNum].GetNext(position); 
					x1 = x0 + (int)(kNormal*vector.y); y1 = y0 - (int)(kNormal*vector.z); 
					if(abs(x1 - point.x)<4 && abs(y1 - point.y)<4) 
					{ 
						m_posPointCatched = posOld; 
						m_vCtrlPointOld = vector; 
						bFind = true; 
						break; 
					} 
				}while(position); 
			} 
			else if(m_nCurrentPane == 1) 
			{ 
				x0 = (m_rectLeft.left + m_rectLeft.right)/2; 
				y0 = (m_rectLeft.top + m_rectLeft.bottom)/2; 
				do{ 
					posOld = position; 
					vector = pDoc->m_alstCtrlPoint[nCurveNum].GetNext(position); 
					x1 = x0 + (int)(kNormal*vector.x); y1 = y0 - (int)(kNormal*vector.z); 
					if(abs(x1 - point.x)<4 && abs(y1 - point.y)<4) 
					{ 
						m_posPointCatched = posOld; 
						m_vCtrlPointOld = vector; 
						bFind = true; 
						break; 
					} 
				}while(position); 
			} 
			else if(m_nCurrentPane == 2) 
			{ 
				x0 = (m_rectTop.left + m_rectTop.right)/2; 
				y0 = (m_rectTop.top + m_rectTop.bottom)/2; 
				do{ 
					posOld = position; 
					vector = pDoc->m_alstCtrlPoint[nCurveNum].GetNext(position); 
					x1 = x0 + (int)(kNormal*vector.y); y1 = y0 + (int)(kNormal*vector.x); 
					if(abs(x1 - point.x)<4 && abs(y1 - point.y)<4) 
					{ 
						m_posPointCatched = posOld; 
						m_vCtrlPointOld = vector; 
						bFind = true; 
						break; 
					} 
				}while(position); 
			} 
		} 
		if(bFind) 
		{ 
			m_nCurrentCurve = nCurveNum; 
			break; 
		} 
	} 
} 
 
void CCurveEditorView::OnMouseMove(UINT nFlags, CPoint point)  
{ 
	VECTOR vector; 
 
	if(m_nCurrentPane==WhichPane(m_pointDown) && m_bDown) 
	{ 
		// user pane 
		if(m_nCurrentPane==3) 
		{ 
			if(m_bScale) 
			{ 
				k = kOld*(1+ (point.y - m_pointDown.y)/100.0); 
				if(k<0.001)k=0.001; 
				DrawAll(); 
			} 
			else if(m_bRotate) 
			{ 
				alpha = alphaOld+ (m_pointDown.x -  point.x )/100.0; 
				theta = thetaOld+ (m_pointDown.y - point.y)/100.0; 
				if(theta<3.14/5)theta=3.14/5; 
				else if(theta>3.14*0.8)theta=3.14*0.8; 
				DrawAll(); 
			} 
		} 
		// other pane 
		else 
		{ 
			// scale function 
			if(m_bScale) 
			{ 
				kNormal = kNormalOld*(1+ (+ point.y - m_pointDown.y)/100.0); 
				DrawAll(); 
			} 
			// other function 
			else if(m_posPointCatched) 
			{ 
				CCurveEditorDoc* pDoc = GetDocument(); 
				ASSERT_VALID(pDoc); 
				// move the current curve's control point 
				switch(m_nCurrentPane) 
				{ 
				case 0: 
					vector.x = m_vCtrlPointOld.x; 
					vector.y = m_vCtrlPointOld.y + (point.x - m_pointDown.x)/kNormal; 
					vector.z = m_vCtrlPointOld.z + (m_pointDown.y - point.y)/kNormal; 
					break; 
				case 1: 
					vector.x = m_vCtrlPointOld.x + (point.x - m_pointDown.x)/kNormal; 
					vector.y = m_vCtrlPointOld.y; 
					vector.z = m_vCtrlPointOld.z + (m_pointDown.y - point.y)/kNormal; 
					break; 
				case 2: 
					vector.x = m_vCtrlPointOld.x + (point.y - m_pointDown.y)/kNormal; 
					vector.y = m_vCtrlPointOld.y + (point.x - m_pointDown.x)/kNormal; 
					vector.z = m_vCtrlPointOld.z; 
				default: 
					break; 
				} 
				pDoc->m_alstCtrlPoint[m_nCurrentCurve].SetAt(m_posPointCatched, vector); 
				// the message format: wParam=function No., lParam=curve No. 
				POINTCHANGED pc; 
				pc.nCurveNum = m_nCurrentCurve; 
				pc.position = m_posPointCatched; 
				::SendMessage(m_hWndObjects, CEV_NOTIFY_MESSAGE, CEVN_UPDATE_CURVE, (LPARAM)&pc); 
				DrawAll(); 
			} 
		} 
		RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); 
	} 
	else if(m_bShowTangent) 
	{ 
		CCurveEditorDoc* pDoc = GetDocument(); 
		ASSERT_VALID(pDoc); 
		POSITION position; 
		int nCount, i; 
		int x0, y0; 
		double t; 
		VECTOR *pvCtrl, vPoint, vTangent; 
		 
		nCount = pDoc->m_alstCtrlPoint[0].GetCount(); 
		pvCtrl = new VECTOR[nCount]; 
		position = pDoc->m_alstCtrlPoint[0].GetHeadPosition(); 
		for(i=0; im_alstCtrlPoint[0].GetNext(position); 
		t = (point.x - 50)/300.0; 
		if(t<0)t=0; 
		if(t>1.0) 
			t=1.0; 
		DeCasteljau(pvCtrl, nCount, t, &vPoint); 
		BezierTangent(pvCtrl, nCount, t, &vTangent); 
		DrawAll(); 
		// Front view 
		x0 = (m_rectFront.left + m_rectFront.right)/2; 
		y0 = (m_rectFront.top + m_rectFront.bottom)/2; 
		vPoint = kNormal*vPoint; 
		vTangent = kNormal*vTangent; 
		m_dcMem.MoveTo((int)(x0+vPoint.y), (int)(y0-vPoint.z)); 
		vTangent = (500.0/Module(vTangent))*vTangent; 
		vTangent = vTangent + vPoint; 
		m_dcMem.LineTo((int)(x0+vTangent.y), (int)(y0-vTangent.z)); 
		RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); 
		delete[] pvCtrl; 
	} 
 
	if(m_bMoveIntersection) 
		ChangeCurve(point); 
 
	m_pointMouse = point; 
	CView::OnMouseMove(nFlags, point); 
} 
 
void CCurveEditorView::OnLButtonUp(UINT nFlags, CPoint point)  
{ 
	// TODO: Add your message handler code here and/or call default 
	if(WhichPane(point) == WhichPane(m_pointDown)) 
		m_nCurrentPane = WhichPane(point); 
 
	DrawAll(); 
	//m_dcMem.FillSolidRect(m_nCurrentPane==0?&m_rectFront: 
	//(m_nCurrentPane==1?&m_rectLeft:(m_nCurrentPane==2?&m_rectTop:&m_rectUser)), 
	//	RGB(0,255,255)); 
	RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); 
 
	m_bDown = false; 
	CView::OnLButtonUp(nFlags, point); 
} 
 
BOOL CCurveEditorView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)  
{ 
	// TODO: Add your message handler code here and/or call default 
	if(m_nCurrentPane==WhichPane(m_pointMouse)) 
	{ 
		if(m_bScale) 
		{ 
			SetCursor(AfxGetApp()->LoadCursor(IDC_VIEW_SCALE)); 
			return 1; 
		} 
		else if(m_bRotate) 
		{ 
			SetCursor(AfxGetApp()->LoadCursor(IDC_VIEW_ROTATE)); 
			return 1; 
		} 
	} 
 
	return CView::OnSetCursor(pWnd, nHitTest, message); 
} 
 
void CCurveEditorView::DrawAll() 
{ 
//	CString str; 
//	str.Format("k=%f, kNormal=%f, alpha=%f, theta=%f", 
//		k, kNormal, alpha*18./3.14, theta*180/3.14); 
 
	DrawSplit(); 
//	m_dcMem.TextOut(10, 10, str); 
	DrawCurve(); 
	DrawCube(); 
	if(m_bAlwaysSplitPoint)DrawSplitPoint(); 
} 
 
int CCurveEditorView::WhichPane(CPoint point) 
{ 
	int nCurrentPane=-1; 
	if(m_rectFront.PtInRect(point)) nCurrentPane = 0; 
	if(m_rectLeft.PtInRect(point)) nCurrentPane = 1; 
	if(m_rectTop.PtInRect(point)) nCurrentPane = 2; 
	if(m_rectUser.PtInRect(point)) nCurrentPane =3; 
 
	return nCurrentPane; 
} 
 
LONG CCurveEditorView::OnMainFrameCommand(WPARAM wParam, LPARAM lParam) 
{ 
	switch(wParam) 
	{ 
	case ID_ROTATE_VIEW: 
		OnRotateView(); 
		break; 
	case ID_SCALE_VIEW: 
		OnScaleView(); 
		break; 
	case ID_INCREASE_CURVE_ORDER: 
		OnIncreaseCurveOrder(); 
		break; 
	case ID_DECREASE_CURVE_ORDER: 
		OnDecreaseCurveOrder(); 
		break; 
	case ID_ALWAYS_SHOW_INTERSECTION: 
		OnAlwaysShowIntersection(); 
		break; 
	default: 
		return -1; 
		break; 
	} 
 
	return 0; 
} 
 
void CCurveEditorView::OnRotateView()  
{ 
	if(m_bRotate) 
	{ 
		m_bRotate = false; 
	} 
	else m_bRotate = true; 
	m_bScale = false; 
} 
 
void CCurveEditorView::OnScaleView()  
{ 
	if(m_bScale) 
	{ 
		m_bScale = false; 
	} 
	else m_bScale = true; 
	m_bRotate = false;	 
} 
 
void CCurveEditorView::OnIncreaseCurveOrder()  
{ 
	int i=0, nCurrentCurve; 
	POSITION position; 
 
	CCurveEditorDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
 
	nCurrentCurve = pDoc->m_nCurrentCurve; 
	int count = pDoc->m_alstCtrlPoint[nCurrentCurve].GetCount(); 
 
	VECTOR *pvOld, *pvNew; 
	pvOld = new VECTOR[count]; 
	pvNew = new VECTOR[count+1]; 
 
	position = pDoc->m_alstCtrlPoint[nCurrentCurve].GetHeadPosition(); 
	while(position) 
		pvOld[i++] = pDoc->m_alstCtrlPoint[nCurrentCurve].GetNext(position); 
	BezierIncreaseOrder(pvOld, pvNew, count); 
 
	position = pDoc->m_alstCtrlPoint[nCurrentCurve].GetHeadPosition(); 
	i=0; 
	while(position) 
	{ 
		pDoc->m_alstCtrlPoint[nCurrentCurve].SetAt(position, pvNew[i++]); 
		pDoc->m_alstCtrlPoint[nCurrentCurve].GetNext(position); 
	} 
	pDoc->m_alstCtrlPoint[nCurrentCurve].AddTail(pvNew[count]); 
	delete[] pvOld; 
	delete[] pvNew; 
	::SendMessage(m_hWndObjects, CEV_NOTIFY_MESSAGE, CEVN_CTRL_POINT_INCREASED, nCurrentCurve); 
	DrawAll(); 
	RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); 
} 
 
void CCurveEditorView::OnDecreaseCurveOrder()  
{ 
	 
} 
 
void CCurveEditorView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	// TODO: Add your message handler code here and/or call default 
	if(nChar==VK_ESCAPE) 
		m_bMoveIntersection = false; 
 
	if(nChar==VK_ESCAPE && !m_bDown) 
	{ 
		m_bScale = m_bRotate = false; 
		((CMainFrame*)AfxGetMainWnd())->EscapeFunction(); 
	} 
	if(nChar==VK_CONTROL && !m_bDown) 
	{ 
		m_bScale = false; 
		m_bRotate = true; 
	} 
	CView::OnKeyDown(nChar, nRepCnt, nFlags); 
} 
 
void CCurveEditorView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	if(nChar==VK_CONTROL) 
	{ 
		m_bRotate = false; 
	} 
	CView::OnKeyUp(nChar, nRepCnt, nFlags); 
} 
 
void CCurveEditorView::OnAlwaysShowIntersection() 
{ 
	// m_bAlwaysShowInts = !m_bAlwaysShowInts; 
} 
 
void CCurveEditorView::OnAlwaysShowSplitPoint()  
{ 
	m_bAlwaysSplitPoint = !m_bAlwaysSplitPoint; 
 
} 
 
void CCurveEditorView::OnUpdateAlwaysShowSplitPoint(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_bAlwaysSplitPoint); 
} 
 
void CCurveEditorView::OnShowTangent()  
{ 
	m_bMoveIntersection = false; 
	m_bShowTangent = !m_bShowTangent; 
} 
 
void CCurveEditorView::OnUpdateShowTangent(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_bShowTangent); 
} 
 
void CCurveEditorView::OnNewCurves()  
{ 
	// make two curves that have one intersection point 
	VECTOR avCtrlPoint[4], avPoint[2][4]; 
	avPoint[0][0].x = 0; 
	avPoint[0][0].y = -500.92; 
	avPoint[0][0].z = -40; 
 
	avPoint[0][1].x = -85.54; 
	avPoint[0][1].y = -118; 
	avPoint[0][1].z = -74; 
 
	avPoint[0][2].x = -110; 
	avPoint[0][2].y = 13.85; 
	avPoint[0][2].z = 77.77; 
 
	avPoint[0][3].x = 34; 
	avPoint[0][3].y = -53; 
	avPoint[0][3].z = 99; 
 
	avPoint[1][0].x = -100.0; 
	avPoint[1][0].y = 10.0; 
	avPoint[1][0].z = 10.0; 
 
//	avPoint[1][1].x = -144.77; 
//	avPoint[1][1].y = 72.77; 
//	avPoint[1][1].z = -15.54; 
	avPoint[1][1] = avPoint[0][1]; 
 
	avPoint[1][2] = avPoint[0][2]; 
 
	avPoint[1][3].x = 44.0; 
	avPoint[1][3].y = -43.00; 
	avPoint[1][3].z = -109.0; 
 
	int i, j; 
	CCurveEditorDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
 
	for(i=0; i<2; i++) 
	{ 
		BezierFit(avPoint[i], 4, avCtrlPoint); 
		pDoc->m_alstCtrlPoint[i].RemoveAll(); 
		for(j=0; j<4; j++) 
			pDoc->m_alstCtrlPoint[i].AddTail(avCtrlPoint[j]); 
	} 
 
	::SendMessage(m_hWndObjects, CEV_NOTIFY_MESSAGE, CEVN_NEW_CURVE, 0); 
	DrawAll(); 
	RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); 
} 
 
void CCurveEditorView::OnMoveIntersection()  
{ 
	m_bShowTangent = false; 
	m_bMoveIntersection = ! m_bMoveIntersection; 
} 
 
void CCurveEditorView::OnUpdateMoveIntersection(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_bMoveIntersection); 
} 
 
void CCurveEditorView::ChangeCurve(CPoint point) 
{ 
	int count, i, j; 
	double *paT[2]; 
	VECTOR vIntPoint; 
 
	CCurveEditorDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
	// make two curves that have two intersection point 
	VECTOR avCtrlPoint[2][4], avPoint[2][4]; 
	avPoint[0][0].x = 110; 
	avPoint[0][0].y = -500.92; 
	avPoint[0][0].z = -40; 
 
	avPoint[0][1].x = 30; 
	avPoint[0][1].y = point.x-400; 
	avPoint[0][1].z = point.y-310; 
 
	avPoint[0][2].x = 40; 
	avPoint[0][2].y = 13.85; 
	avPoint[0][2].z = 77.77; 
 
	avPoint[0][3].x = 30; 
	avPoint[0][3].y = -53; 
	avPoint[0][3].z = 99; 
 
	avPoint[1][0].x = 80; 
	avPoint[1][0].y = 10.0; 
	avPoint[1][0].z = 10.0; 
 
//	avPoint[1][1].x = -144.77; 
//	avPoint[1][1].y = 72.77; 
//	avPoint[1][1].z = -15.54; 
	avPoint[1][1] = avPoint[0][1]; 
 
	avPoint[1][2] = avPoint[0][2]; 
 
	avPoint[1][3].x = 0; 
	avPoint[1][3].y = -43.00; 
	avPoint[1][3].z = -109.0; 
 
	for(i=0; i<2; i++) 
	{ 
		BezierFit(avPoint[i], 4, avCtrlPoint[i]); 
		pDoc->m_alstCtrlPoint[i].RemoveAll(); 
		for(j=0; j<4; j++) 
			pDoc->m_alstCtrlPoint[i].AddTail(avCtrlPoint[i][j]); 
	} 
	::SendMessage(m_hWndObjects, CEV_NOTIFY_MESSAGE, CEVN_NEW_CURVE, 0); 
	DrawAll(); 
 
 
	paT[0] = new double[16]; 
	paT[1] = new double[16]; 
	ASSERT(paT[0] && paT[1]); 
 
	count = Intersection(avCtrlPoint[0], 4, avCtrlPoint[1], 4, paT[0], paT[1], 16); 
	CString str; 
	str.Format("count = %d, x = %d, y = %d", count, point.x, point.y); 
	m_dcMem.TextOut(10, 10, str); 
 
	int x0, y0, x1, y1; 
	x0 = (m_rectFront.left + m_rectFront.right)/2; 
	y0 = (m_rectFront.top + m_rectFront.bottom)/2; 
	for(i=0; i<2; i++) 
		for(j=0; j