#include "StdAfx.h" #include ".\itemcurveedit.h" #include "SigmaDoc.h" #include "SigmaView.h" #include ".\actionmodifieditem.h" #include "ActionBackupItem.h" #include "DrawOperator/TypeDefine.h" #include "ActionCurveEdit.h" #include "ActionCurveEditAddPoint.h" #include "ActionCurveEditDeletePoint.h" #include "HandleDrawer.h" namespace NItem { #define TRACKER_SOLID 1 #define TRACKER_RECT 2 #define TRACKER_CIRCLE 4 #define TRACKER_NO_EDIT TRACKER_SOLID | TRACKER_CIRCLE CItemCurveEdit::CItemCurveEdit(CSigmaDoc* pDoc) : CItemCurve(pDoc) , m_bLButtonDwonWhenMoueseMove(false) , m_nHandleDrawMode(TRACKER_CIRCLE) , m_pBakOne(nullptr) , m_nModeX(-1) , m_nModeY(-1) , typeIndex(0) , m_handleDrawer(nullptr) { width = 0; m_nBeginIndex = 0; m_nEndIndex = 0; m_pMarkCurve = nullptr; this->SetType(ITEM_CURVE_EDIT); m_pAttachAction = nullptr; m_handleDrawer = new HandleDrawer(pDoc); } CItemCurveEdit::~CItemCurveEdit(void) { Clear(); delete m_handleDrawer; m_handleDrawer = 0; //if(m_pAttachAction) // delete (CActionListItem*)m_pAttachAction; } void CItemCurveEdit::Clear(void) { if (m_pBakOne) { delete m_pBakOne; m_pBakOne = nullptr; } if (m_pMarkCurve) { delete m_pMarkCurve; m_pMarkCurve = nullptr; } //获得曲线范围以便更新客户区 if (GetPos() != nullptr) { COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos()); CRect8 range(1e100, -1e100, -1e100, 1e100); pOne->GetRange(range); CRect rt = GetDC()->GetScreen(range); rt.NormalizeRect(); rt.InflateRect(GetDoc()->GetHandleSize()); rt.InflateRect(1, 1); //GetDoc()->Invalidate(&rt); } } void CItemCurveEdit::SetPos(POSITION pos) { CItem::SetPos(pos); if (m_pBakOne) { delete m_pBakOne; m_pBakOne = nullptr; } if (pos) { COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos()); //COne* pOne = GetDoc()->GetDraw()->GetAt(pos); m_pBakOne = new COne; *m_pBakOne = *pOne; GetMarkCurve(); } } void CItemCurveEdit::GetMarkCurve(void) { if (GetPos() == nullptr) return; COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos()); CCurveEx* pc = (CCurveEx*)pOne->GetValue(); if (m_pMarkCurve == nullptr) m_pMarkCurve = new CCurveEx; CCurveRedundant m_redundant; m_redundant.SetCurve(*pc); double err = GetDC()->GetMiniSmoothStep() * 3;//fabs(pc->l[pc->num-1]-pc->l[0]) * 0.01; m_redundant.Execute(err); m_redundant.GetRedundantCurve(*m_pMarkCurve); m_pMarkCurve->nPoint = 4; m_pMarkCurve->bAutoLocation = FALSE; } CRect CItemCurveEdit::GetFirstNodeHandleRectFocus(CPoint point) { CRect rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point); rt.InflateRect(1, 1); return rt; } void CItemCurveEdit::SetDrawMode(int nModeX, int nModeY) { m_nModeX = nModeX; m_nModeY = nModeY; } //为了编辑速度谱 void CItemCurveEdit::GetXY(CCurveEx* pValue, int nIndex, dfPoint& point) { point.x0 = pValue->x[nIndex]; point.y0 = pValue->y[nIndex]; point.z0 = pValue->z[nIndex]; point.l = pValue->l[nIndex]; } void CItemCurveEdit::DrawHandle(CXyDC* pDC, CCurveEx* pCurve) { if (pCurve == nullptr) return; CPoint ptPrev; CRect rt; dfPoint pt; CPoint point; for (int i = 0;i < pCurve->num;i++) { //draw handle GetXY(pCurve, i, pt); point.x = pDC->GetSX(pt.x0); point.y = pDC->GetSY(pt.y0); if (i > 0) { if (point.x == ptPrev.x && point.y == ptPrev.y && i != GetHandleIndex()) continue; } if (i == GetHandleIndex()) { if (i == 0)//第一个节点,为了能看出第一个节点在哪里 rt = GetFirstNodeHandleRectFocus(point); else rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point); } else { if (i == 0)//第一个节点,为了能看出第一个节点在哪里 rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point); else rt = GetDoc()->m_itemTracker.GetHandleRect(point); } GetDoc()->m_itemTracker.DrawHandle(m_pScreenDC, rt, TRACKER_CIRCLE); // m_nHandleDrawMode); ptPrev = point; } } void CItemCurveEdit::OnDraw(CXyDC* pDC) { //使用CXDC有时画不出图。不使用此函数。 POSITION pos = GetPos(); if (pos == 0) return; switch (GetOffsetMode()) { default: DrawHandle(pDC, (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos())); break; case DRAG_NODE_SPLINE: DrawHandle(pDC, m_pMarkCurve); break; } } void CItemCurveEdit::Draw(CDC* pDC) { POSITION pos = GetPos(); if (pos == 0) return; CCurveEx* pValue = GetCurCurve(); DrawHandlesByCDC(pDC, pValue); } void CItemCurveEdit::DrawAssistant(CDC* pDC, int mouseX, int mouseY) { CCurveEx* pCurvve = nullptr; switch (GetOffsetMode()) { default: //DrawHandlesByCDC(pDC, (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos())); pCurvve = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos()); break; case DRAG_NODE_SPLINE: //DrawHandle(pDC, m_pMarkCurve); pCurvve = m_pMarkCurve; break; } //CCurveEx * pCurvve = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos()); m_handleDrawer->Init(pCurvve); m_handleDrawer->DrawAll(pDC); } int CItemCurveEdit::GetNumberOfNode() { CCurveEx* pc = GetCurCurve(); if (pc == 0) return -1; return pc->num; } void CItemCurveEdit::EreaseHandles(CDC* pDC) { m_handleDrawer->ClearAll(pDC); } void CItemCurveEdit::DrawHandlesByCDC(CDC* pDC, CCurveEx* pCurve) { if (pCurve == nullptr) return; m_handleDrawer->ClearAll(pDC); m_handleDrawer->Init(pCurve); m_handleDrawer->DrawAll(pDC); } void CItemCurveEdit::OnLButtonDblClk(UINT nFlags, CPoint point) { POSITION pos = GetPos(); if (pos == nullptr) { return; } COne* pOne = GetDoc()->GetDraw()->GetAt(pos); if (pOne == nullptr) { return; } std::unique_ptr pAction = std::make_unique(GetDoc(), 0); pAction->BackupOldItem(pos, pOne); if (GetHandleIndex() >= 0) { if (IsCaptureState()) ReleaseCapture(); int index = GetHandleIndex(); CCurveEx* pcurve = GetCurCurve(); CRect8 range(1e300, -1e300, -1e300, 1e300); for (int i = index - 1;i <= index + 1;i++) { if (i<0 || i>pcurve->num - 1)continue; range.CombinRect(pcurve->x[i], pcurve->y[i], pcurve->x[i], pcurve->y[i]); } DeleteHandle(GetHandleIndex()); SetHandleIndex(-1); CRect rt = GetDC()->GetScreen(range); CSize8 sz = GetDoc()->GetSelectSize(); CSize size((int)sz.cx + 1, (int)sz.cy + 1); rt.InflateRect(size); } else if (IsCanAddHandle(point)) { int ret = AddHandle(point); if (ret < 0) { return; } } pAction->BackupNewItem(); GetDoc()->SetActionItem(pAction.release()); GetDoc()->Modified(); if (GetDoc()->GetItem()->GetType() == ITEM_CURVE_EDIT) { EndEdit(); } } CRect CItemCurveEdit::GetRangeWidthIndex(int nIndex) { CCurveEx* pValue = GetCurCurve();//(CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos()); CRect8 rt(pValue->x[nIndex], pValue->y[nIndex], pValue->x[nIndex], pValue->y[nIndex]); if (nIndex > 0) rt.CombinRect(pValue->x[nIndex - 1], pValue->y[nIndex - 1], pValue->x[nIndex - 1], pValue->y[nIndex - 1]); if (nIndex < pValue->num - 1) rt.CombinRect(pValue->x[nIndex + 1], pValue->y[nIndex + 1], pValue->x[nIndex + 1], pValue->y[nIndex + 1]); CRect rect = GetDC()->GetScreen(rt); rect.InflateRect(GetDoc()->GetHandleSize()); return rect; } void CItemCurveEdit::OnLButtonDown(CDC* pDC, UINT nFlags, CPoint point, int vk) { if (this->GetHandleIndex() < 0) { if (!IsCanAddHandle(point)) return; } if (NewPointList.GetCount() > 0) NewPointList.RemoveAll(); //GetView()->SetCapture(); m_nLButtonDownPoint = point; c_down = GetDC()->GetReal(point); c_last = c_down; switch (GetOffsetMode()) { default: DrawMoveLine(); break; case DRAG_NODE_SPLINE: break; } } void CItemCurveEdit::OnLButtonUp(CDC* pDC, UINT nFlags, CPoint point, int vk) { if (m_bLButtonDwonWhenMoueseMove == false) return; m_bLButtonDwonWhenMoueseMove = true; if (this->GetHandleIndex() < 0) { //直接编辑另一条曲线 CPoint2D pt = GetDC()->GetReal(point); POSITION pos = GetDoc()->GetSelectedItem(pt); if (pos == GetPos()) return; //为当前编辑曲线时返回 EndEdit(); return; } c_last = GetDC()->GetReal(point); switch (GetOffsetMode()) { default: case DRAG_NODE_DEFAULT: DrawMoveLine(); break; case DRAG_NODE_LINE: //线性移动节点 case DRAG_NODE_COS: //余弦移动节点 if (NewPointList.GetCount() > 0) DrawMoveLine(NewPointList, TRUE); else return; break; case DRAG_NODE_SPLINE: if (NewPointList.GetCount() > 0) DrawMoveLine(NewPointList, FALSE); else return; break; } if (c_last == c_down && GetOffsetMode() != DRAG_NODE_SPLINE) return; //设置曲线坐标 OnDragPointEnding(nullptr); //便于增加其它处理,在结束后 OnDragPointEnd(GetHandleIndex()); SetModifiedFlag(TRUE); GetDoc()->Modified(); SetHandleIndex(-1); ReleaseCapture(); } void CItemCurveEdit::OnDragPointEnding(CPointList* pList) { BOOL bRedraw = TRUE; //是否进行曲线绑定编辑 //BOOL bAttachProcess = GetPreferences().WorkaroundEdit.m_bCurveBindEdit; BOOL bAttachProcess = TRUE; CCurveEx* pValue = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos()); if (pList) { CCurveEx* pc = new CCurveEx; *pc = *pValue; pValue = pc; bRedraw = FALSE; bAttachProcess = FALSE; } CPointList oldPoints; CPointList newPoints; int i; dfPoint pt; CRect rt; switch (GetOffsetMode()) { default: case DRAG_NODE_DEFAULT: { i = GetHandleIndex(); if (bRedraw) { rt = GetRangeWidthIndex(i); //GetDoc()->Invalidate(&rt); } //为了绑定处理,记录原坐标点 if (bAttachProcess) { if (i - 1 >= 0) { pValue->GetPoint(i - 1, pt); oldPoints.AddTail(pt); } pValue->GetPoint(i, pt); oldPoints.AddTail(pt); if (i + 1 <= pValue->num - 1) { pValue->GetPoint(i + 1, pt); oldPoints.AddTail(pt); } } CActionCurveEdit* pAction = 0; if (pList == nullptr) //鼠标移动时 传入pList 在鼠标左键抬起时 传入的pList为空 程序只在鼠标左键抬起时才会开启移动节点的Undo/Redo功能 { pAction = new CActionCurveEdit(GetDoc(), 0, GetPos()); //更新坐标 pAction->BackupUndoNode(i, pValue->x[i], pValue->y[i]); } pValue->x[i] += (c_last.x0 - c_down.x0); pValue->y[i] += (c_last.y0 - c_down.y0); if (pValue->bAutoLocation) pValue->GetLocation(); if (pList == nullptr) { pAction->BackupRedoNode(i, pValue->x[i], pValue->y[i]); GetDoc()->SetActionItem(pAction); } if (bAttachProcess) { //为了绑定处理,记录新坐标点 if (i - 1 >= 0) { pValue->GetPoint(i - 1, pt); newPoints.AddTail(pt); } pValue->GetPoint(i, pt); newPoints.AddTail(pt); if (i + 1 <= pValue->num - 1) { pValue->GetPoint(i + 1, pt); newPoints.AddTail(pt); } AttachProcess(oldPoints, newPoints); } if (bRedraw) { rt = GetRangeWidthIndex(i); //GetDoc()->Invalidate(&rt); } } break; case DRAG_NODE_LINE: //线性移动节点 case DRAG_NODE_COS: //余弦移动节点 { CRect8 range1, range2; range1.SetRect(1e100, -1e100, -1e100, 1e100); range2 = range1; dfPoint dp; POSITION pos = NewPointList.GetHeadPosition(); for (i = m_nBeginIndex; i <= m_nEndIndex; i++) { dp = NewPointList.GetNext(pos); range1.CombinRect(pValue->x[i], pValue->y[i], pValue->x[i], pValue->y[i]); //为了绑定处理,记录原坐标点 if (bAttachProcess) { pValue->GetPoint(i, pt); oldPoints.AddTail(pt); } //更新坐标 pValue->x[i] = dp.x0; pValue->y[i] = dp.y0; range2.CombinRect(dp.x0, dp.y0, dp.x0, dp.y0); //为了绑定处理,记录新坐标点 if (bAttachProcess) { pValue->GetPoint(i, pt); newPoints.AddTail(pt); } } if (pValue->bAutoLocation) pValue->GetLocation(); //绑定处理 if (bAttachProcess) { if (oldPoints.GetCount() > 0) AttachProcess(oldPoints, newPoints); } if (bRedraw) { rt = GetDC()->GetScreen(range1); rt.InflateRect(GetDoc()->GetHandleSize()); //GetDoc()->Invalidate(&rt); rt = GetDC()->GetScreen(range2); rt.InflateRect(GetDoc()->GetHandleSize()); //GetDoc()->Invalidate(&rt); } } break; case DRAG_NODE_SPLINE: { dfPoint dp; PointList.RemoveAll(); int i, j; for (i = 0; i < m_nBeginIndex; i++) { pValue->GetPoint(i, dp); PointList.AddTail(dp); } POSITION pos = NewPointList.GetHeadPosition(); while (pos) { dp = NewPointList.GetNext(pos); PointList.AddTail(dp); //为了绑定处理,记录新坐标点 if (bAttachProcess) newPoints.AddTail(dp); } if (m_nEndIndex < pValue->num - 1) for (i = m_nEndIndex;i < pValue->num;i++) { pValue->GetPoint(i, dp); PointList.AddTail(dp); } if (bRedraw) Invalidate(); //为了绑定处理,记录原坐标点 if (bAttachProcess) { for (i = m_nBeginIndex; i <= m_nEndIndex; i++) { pValue->GetPoint(i, pt); oldPoints.AddTail(pt); } } //改变曲线桩号,使其成为自动计算方式 if (pValue->nPoint == 4) pValue->nPoint = 3; if (!pValue->bAutoLocation) pValue->bAutoLocation = TRUE; //设置曲线坐标 pValue->SetPoints(PointList, pValue->nPoint, pValue->bAutoLocation); PointList.RemoveAll(); //为了绑定处理,记录原坐标点 if (bAttachProcess) { //绑定处理 if (oldPoints.GetCount() > 0) AttachProcess(oldPoints, newPoints); } if (bRedraw) { m_pMarkCurve->x[GetHandleIndex()] = c_last.x0; m_pMarkCurve->y[GetHandleIndex()] = c_last.y0; for (i = 0;i < m_pMarkCurve->num;i++) { j = pValue->FindIndex(m_pMarkCurve->x[i], m_pMarkCurve->y[i], -1); if (j >= 0) m_pMarkCurve->l[i] = pValue->l[j]; } Invalidate(); } } break; } if (pList) { pValue->GetPoint(*pList); delete pValue; } } void CItemCurveEdit::AttachProcess(CPointList& oldPoints, CPointList& newPoints) //绑定处理坐标相同的曲线 { } int CItemCurveEdit::OnMouseMove(CDC* dc, UINT nFlags, CPoint point) { SetScreenDC(dc); m_nMouseMovePoint = point; POSITION pos = GetPos(); if (pos == 0) return 1; CXyDC* pDC = GetDC(); if (nFlags & 1) //鼠标左键下按 { m_bLButtonDwonWhenMoueseMove = true; //当没有选择节点,而且能增加时,只要左键按下移动时自动增加一个节点 int i = GetHandleIndex(); if (i < 0) { CSize8 sz = GetDoc()->GetSelectSize(); //当移动的距离大于选择半径时才能增加新点,防止意外增加点 if (AfxGetPublicFunction()->Distance(m_nLButtonDownPoint.x, m_nLButtonDownPoint.y, point.x, point.y) > sz.cx) { i = AddHandle(m_nLButtonDownPoint); if (i < 0) return 1; SetHandleIndex(i); if (GetOffsetMode() != DRAG_NODE_SPLINE) DrawMoveLine(); } else return 1; } //如果左键没有按下,则放弃 //if(!(nFlags & MK_LBUTTON)) //{ // ReleaseCapture(); // return; //} //显示移动的曲线 switch (GetOffsetMode()) { default: case DRAG_NODE_DEFAULT: DrawMoveLine();//擦除上一次线 c_last = pDC->GetReal(point); DrawMoveLine();//画当前线 break; case DRAG_NODE_LINE: //线性移动节点 case DRAG_NODE_COS: //余弦移动节点 { if (NewPointList.GetCount() > 0) { DrawMoveLine(NewPointList, TRUE); NewPointList.RemoveAll(); } m_nBeginIndex = -1; m_nEndIndex = -1; c_last = pDC->GetReal(point); GetDragPoint(c_last, NewPointList, m_nBeginIndex, m_nEndIndex); if (NewPointList.GetCount() > 0) DrawMoveLine(NewPointList, TRUE); } break; case DRAG_NODE_SPLINE: { if (NewPointList.GetCount() > 0) { DrawMoveLine(NewPointList, FALSE); NewPointList.RemoveAll(); DrawHandle(GetDC(), c_last.x0, c_last.y0); } m_nBeginIndex = -1; m_nEndIndex = -1; c_last = pDC->GetReal(point); GetDragSplinePoint(c_last, NewPointList, m_nBeginIndex, m_nEndIndex); if (NewPointList.GetCount() > 0) { DrawMoveLine(NewPointList, FALSE); DrawHandle(GetDC(), c_last.x0, c_last.y0); } } break; } //设置状态条信息//////////////////////////////////////////////////////////////////////////////// CPointList list; OnDragPointEnding(&list); CString str, string; CCurveEx* curve = new CCurveEx; curve->SetPoints(list, 2); COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos()); CCurveEx* pValue = (CCurveEx*)pOne->GetValue(); if (pValue->name == nullptr) string.Format("Pline, area=%lf, Length=%lf", curve->Area(), curve->Length()); else string.Format("Pline.%s, area=%lf, Length=%lf", pValue->name, curve->Area(), curve->Length()); str.Format("Layer=%s, %s", pOne->GetLayer()->GetPathName(), string); //GetDoc()->SetStatusBarInfo(0, str); delete curve; //////////////////////////////////////////////////////////////////////////////////////////////// OnDragPointMove(GetHandleIndex(), c_last); return 1; } //m_handleDrawer->ReDrawAll(pDC); // //TODO:要重写这段代码 CCurveEx* pValue = GetCurCurve(); if (pValue == 0) { SetHandleIndex(-1); int handleIndex = m_handleDrawer->EreaseFocusHandle(dc); m_handleDrawer->DrawOneHandle(dc, handleIndex); } else { int i = HitTestHandle(pValue, point); if (i >= 0) { SetHandleIndex(i); } else { SetHandleIndex(-1); int handleIndex = m_handleDrawer->EreaseFocusHandle(dc); m_handleDrawer->DrawOneHandle(dc, handleIndex); } } // m_handleDrawer->DrawFocusHandle(dc, GetHandleIndex()); return 1; } void CItemCurveEdit::DrawOrEraseSelectHandleForMouseMove(CPoint point) { CRect rt; CXyDC* pDC = GetDC(); CCurveEx* pValue = GetCurCurve(); int i = HitTestHandle(pValue, point); if (i >= 0 && i != GetHandleIndex()) { if (GetHandleIndex() >= 0) { //擦除旧的节点 rt = GetDoc()->m_itemTracker.GetHandleRectFocus(pDC->GetSX(pValue->x[GetHandleIndex()]), pDC->GetSY(pValue->y[GetHandleIndex()])); GetDoc()->m_itemTracker.DrawHandle(m_pScreenDC, rt, m_nHandleDrawMode); } //绘制出选中的节点 DrawSelectHandle(i); SetHandleIndex(i); } else if (i < 0 && GetHandleIndex() >= 0) { //擦除上一次绘制的选中节点 DrawSelectHandle(GetHandleIndex()); SetHandleIndex(-1); } } void CItemCurveEdit::DrawSelectHandle(int nHandle) { CCurveEx* pValue = GetCurCurve(); if (nHandle<0 || nHandle>pValue->num - 1) return; CPoint point; point.x = GetDC()->GetSX(pValue->x[nHandle]); point.y = GetDC()->GetSY(pValue->y[nHandle]); CRect rt; if (nHandle == 0)//第一个节点,为了能看出第一个节点在哪里 rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point); else rt = GetDoc()->m_itemTracker.GetHandleRect(point); GetDoc()->m_itemTracker.DrawHandle(m_pScreenDC, rt, m_nHandleDrawMode); if (nHandle == 0) rt = GetFirstNodeHandleRectFocus(point); else rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point); GetDoc()->m_itemTracker.DrawHandle(m_pScreenDC, rt, m_nHandleDrawMode); } void CItemCurveEdit::SetModifiedFlag(BOOL bModified) { CItem::SetModifiedFlag(bModified); } BOOL CItemCurveEdit::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { return TRUE; } int CItemCurveEdit::GetSubMenu() { return 6; } void CItemCurveEdit::EndEdit(void) { if (GetPos() == nullptr) return; COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos()); //获得曲线范围以便更新客户区 CRect8 range(1e100, -1e100, -1e100, 1e100); pOne->GetRange(range); CRect rt = GetDC()->GetScreen(range); rt.NormalizeRect(); rt.InflateRect(GetDoc()->GetHandleSize()); rt.InflateRect(1, 1); if (((CCurveEx*)pOne->GetValue())->num < 2) { if (::AfxMessageBox(IDS_STRING_CURVE_ONLY_ONE_POINT, MB_YESNO | MB_ICONQUESTION) == IDYES) { *pOne = *m_pBakOne; CPositionList list;list.AddTail(GetPos()); CItem::SetPos(nullptr); GetDoc()->InvalidateDelete(list); //GetDoc()->Invalidate(&rt); return; } } //为UNDO做准备 if (IsModified()) { //当前线的编辑备份 CActionItem* pAction = new CActionModifiedItem(GetDoc(), IDS_STRING_TOOLBAR_EDIT); ((CActionModifiedItem*)pAction)->BackupOldItem(GetPos(), m_pBakOne); //绑定线的编辑备份 //BOOL bAttachProcess = GetPreferences().WorkaroundEdit.m_bCurveBindEdit; BOOL bAttachProcess = TRUE; if (bAttachProcess && m_pAttachAction != nullptr) { } GetDoc()->SetActionItem(pAction); } //GetDoc()->Invalidate(&rt); } CCurveEx* CItemCurveEdit::GetCurCurve(void) { if (GetOffsetMode() == DRAG_NODE_SPLINE) return m_pMarkCurve; POSITION pos = GetPos(); if (pos == nullptr) return nullptr; return (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(pos); } void CItemCurveEdit::DeleteHandle(int nIndex) { CCurveEx* pValue = GetCurCurve(); //是否进行曲线绑定编辑 //BOOL bAttachProcess = GetPreferences().WorkaroundEdit.m_bCurveBindEdit; BOOL bAttachProcess = TRUE; CPointList oldPoints; CPointList newPoints; if (bAttachProcess) { dfPoint pt; if (nIndex != 0) { pValue->GetPoint(nIndex - 1, pt); oldPoints.AddTail(pt); newPoints.AddTail(pt); } pValue->GetPoint(nIndex, pt); oldPoints.AddTail(pt); if (nIndex < pValue->num - 1) { pValue->GetPoint(nIndex + 1, pt); oldPoints.AddTail(pt); newPoints.AddTail(pt); } } PointList.RemoveAll(); dfPoint dd; for (int i = 0;i < pValue->num;i++) { dd.x0 = pValue->x[i]; dd.y0 = pValue->y[i]; dd.z0 = pValue->z[i]; dd.l = pValue->l[i]; if (i == nIndex) { continue; } PointList.AddTail(dd); } pValue->SetPoints(PointList, pValue->nPoint, pValue->bAutoLocation); this->SetHandleIndex(-1); PointList.RemoveAll(); SetModifiedFlag(TRUE); //为了绑定处理,记录原坐标点 if (bAttachProcess) { //绑定处理 if (oldPoints.GetCount() > 0) AttachProcess(oldPoints, newPoints); } } BOOL CItemCurveEdit::InsertHandleWithPointDistance(double x, double y) { CCurveEx* pValue = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos()); double l0; if (pValue->PointDistance(x, y, l0) > 1e30) return FALSE; return AddHandle(l0); } int CItemCurveEdit::AddHandle(CCurveEx* pValue, dfPoint add) { if (pValue == nullptr) return -1; int nIndex = -1; PointList.RemoveAll(); if (add.l < pValue->l[0]) //将新节点添加到头部 { pValue->GetPoint(PointList); PointList.AddHead(add); nIndex = 0; } else if (add.l > pValue->l[pValue->num - 1]) //将新节点添加到尾部 { pValue->GetPoint(PointList); PointList.AddTail(add); nIndex = (int)PointList.GetCount() - 1; } else //将节点添加到曲线的中间 { dfPoint dd; for (int i = 0;i < pValue->num;i++) { dd.x0 = pValue->x[i]; dd.y0 = pValue->y[i]; dd.z0 = pValue->z[i]; dd.l = pValue->l[i]; PointList.AddTail(dd); if (i == pValue->num - 1)break; if (add.l > pValue->l[i] && add.l < pValue->l[i + 1]) { PointList.AddTail(add); nIndex = i + 1; } } } pValue->SetPoints(PointList, pValue->nPoint, pValue->bAutoLocation); PointList.RemoveAll(); GetDoc()->Modified(); SetModifiedFlag(TRUE); CPoint point = GetDC()->GetScreen(add.x0, add.y0); //CRect rt=GetDoc()->ItemTracker.GetHandleRect(point.x,point.y); //GetDoc()->Invalidate(&rt); this->SetHandleIndex(-1); return nIndex; } int CItemCurveEdit::AddHandle(CPoint point) { double l0; if (!IsCanAddHandle(point, &l0)) return -1; return AddHandle(l0); } int CItemCurveEdit::AddHandle(double l0) { CCurveEx* pValue = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos()); dfPoint add; add.l = l0; pValue->GetCoordinate(add.l, add.x0, add.y0, add.z0); if (GetOffsetMode() == DRAG_NODE_SPLINE) pValue = m_pMarkCurve; return AddHandle(pValue, add); } BOOL CItemCurveEdit::IsCanAddHandle(CPoint point, double* pl0) { POSITION pos = GetPos(); if (pos == nullptr) return FALSE; CCurveEx* pValue = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(pos); if (pValue == nullptr) { return FALSE; } CPoint2D pt = GetDC()->GetReal(point); double l0; double dis = pValue->PointDistance(pt.x0, pt.y0, l0); CSize8 sz = GetDoc()->GetSelectSize(); int dx = GetDC()->GetScreenWidth(dis); int dy = GetDC()->GetScreenHeight(dis); if (pl0) *pl0 = l0; if (dx > sz.cx || dy > sz.cy) return FALSE; return TRUE; } void CItemCurveEdit::CancelAll(void) { if (m_pBakOne) { COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos()); *pOne = *m_pBakOne; GetMarkCurve(); } } BOOL CItemCurveEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch (nChar) { case VK_ESCAPE: if (!IsCaptureState())break; DrawMoveLine();//擦除上一次线 DrawSelectHandle(GetHandleIndex()); SetHandleIndex(-1); ReleaseCapture(); return TRUE; case VK_DELETE: break; case '1': //单点式 //GetView()->OnCurveEditMoveNodeSingle(); return TRUE; case '2': //余弦式 //GetView()->OnCurveEditMoveNodeCosine(); return TRUE; case '3': //三次样条曲线 //GetView()->OnCurveEditMoveNodeSpline(); return TRUE; case '4': //线性式 //GetView()->OnCurveEditMoveNodeLinear(); return TRUE; } return FALSE; } BOOL CItemCurveEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { switch (nChar) { case VK_ESCAPE: EndEdit(); //GetDoc()->EnableDefaultTool(); return TRUE; default: break; } return FALSE; } int CItemCurveEdit::HitTestHandle(CPoint point) { CCurveEx* pValue = GetCurCurve(); if (pValue == nullptr) return -1; CRect rt; for (int i = 0; i < pValue->num; i++) { rt = GetDoc()->m_itemTracker.GetHandleRect(GetDC()->GetSX(pValue->x[i]), GetDC()->GetSY(pValue->y[i])); if (rt.PtInRect(point)) return i; } return -1; } int CItemCurveEdit::HitTestHandle(CCurveEx* pValue, CPoint point) { if (pValue == nullptr) return -1; CRect rt; for (int i = 0;i < pValue->num;i++) { rt = GetDoc()->m_itemTracker.GetHandleRect(GetDC()->GetSX(pValue->x[i]), GetDC()->GetSY(pValue->y[i])); if (rt.PtInRect(point)) return i; } return -1; } BOOL CItemCurveEdit::IsCanCancelAll(void) { return m_pBakOne != nullptr ? TRUE : FALSE; } void CItemCurveEdit::DrawMoveLine(void) { int i = GetHandleIndex(); if (i < 0) return; CXyDC* pDC = GetDC(); CPen pen(PS_SOLID, 0, DRAG_LINE_COLOR); CPen* op = (CPen*)m_pScreenDC->SelectObject(&pen); int od = m_pScreenDC->SetROP2(R2_NOTXORPEN); CCurveEx* pValue = GetCurCurve(); double dx = c_last.x0 - c_down.x0; double dy = c_last.y0 - c_down.y0; dfPoint pt; if (i > 0) { GetXY(pValue, i - 1, pt); CPoint ptS1 = pDC->GetScreen(pt); m_pScreenDC->MoveTo(ptS1); GetXY(pValue, i, pt); pt.x0 += dx; pt.y0 += dy; CPoint ptS2 = pDC->GetScreen(pt); m_pScreenDC->LineTo(ptS2.x, ptS2.y); } if (i < pValue->num - 1) { GetXY(pValue, i + 1, pt); CPoint ptS1 = pDC->GetScreen(pt); m_pScreenDC->MoveTo(ptS1); GetXY(pValue, i, pt); pt.x0 += dx; pt.y0 += dy; CPoint ptS2 = pDC->GetScreen(pt); m_pScreenDC->LineTo(ptS2.x, ptS2.y); } m_pScreenDC->SetROP2(od); m_pScreenDC->SelectObject(op); GetXY(pValue, i, pt); } void CItemCurveEdit::DrawMoveLine(CPointList& NewPointList, BOOL bDrawNode) { if (NewPointList.IsEmpty()) return; CXyDC* pDC = GetDC(); CPen pen(PS_SOLID, 0, DRAG_LINE_COLOR); CPen* op = m_pScreenDC->SelectObject(&pen); int od = m_pScreenDC->SetROP2(R2_NOTXORPEN); dfPoint dp1, dp2; CRect rt; POSITION pos; dp1 = NewPointList.GetHead(); if (bDrawNode) { } pos = NewPointList.GetHeadPosition(); if (pos) NewPointList.GetNext(pos); while (pos) { dp2 = NewPointList.GetNext(pos); CPoint ptS1 = pDC->GetScreen(dp1); m_pScreenDC->MoveTo(ptS1); CPoint ptS2 = pDC->GetScreen(dp2); m_pScreenDC->LineTo(ptS2); dp1 = dp2; if (bDrawNode) { } } m_pScreenDC->SetROP2(od); m_pScreenDC->SelectObject(op); } void CItemCurveEdit::OnDragPointEnd(int nIndex) { } void CItemCurveEdit::OnDragPointMove(int nIndex, CPoint2D pt) { } double CItemCurveEdit::GetPointOffset(double offset, int nMode) { switch (nMode) { case DRAG_NODE_LINE://线性移动节点 offset = 1.0 - offset; break; case DRAG_NODE_COS://余弦移动节点 offset = 1.0 + cos(PI * offset); offset *= offset * 0.25; break; } return offset; } //编辑曲线时,拉动一点时,使邻点进行线性拉动 //dp为新点坐标,begin存储线性计算后的需重画第一点,end存储线性计算后的最后一点 //NewPointList存储已经改变的点(为了下次擦除) void CItemCurveEdit::GetDragPoint(CPoint2D& dp, CPointList& NewPointList, int& begin, int& end) { int i = GetHandleIndex(); if (i < 0) return; NewPointList.RemoveAll(); CCurveEx* pValue = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos()); dfPoint cp, t; double distance, x0, y0, d; int j; begin = i; end = i; distance = 9; GetXY(pValue, i, cp); //画前部分 for (j = i; j >= 0; j--) { GetXY(pValue, j, t); d = fabs(t.l - cp.l); begin = j; if (d >= distance) { NewPointList.AddHead(t); break; } x0 = GetPointOffset(d / distance, GetOffsetMode()); y0 = (x0) * (dp.y0 - cp.y0); x0 = (x0) * (dp.x0 - cp.x0); t.Offset(x0, y0); NewPointList.AddHead(t); } //画后部分 for (j = i + 1; j < pValue->num; j++) { GetXY(pValue, j, t); d = fabs(t.l - cp.l); end = j; if (d >= distance) { NewPointList.AddTail(t); break; } x0 = GetPointOffset(d / distance, GetOffsetMode()); y0 = (x0) * (dp.y0 - cp.y0); x0 = (x0) * (dp.x0 - cp.x0); t.Offset(x0, y0); NewPointList.AddTail(t); } } void CItemCurveEdit::GetDragSplinePoint(CPoint2D& dp, CPointList& NewPointList, int& begin, int& end) { int i = GetHandleIndex(); if (i < 0) return; CCurveEx* pValue = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos()); begin = i - 1; if (begin < 0) begin = 0; end = i + 1; if (end > m_pMarkCurve->num - 1) end = m_pMarkCurve->num - 1; //备份开始结束索引号 int ib = begin; int ie = end; //为了使曲线光滑过渡 double bl = m_pMarkCurve->l[begin]; double el = m_pMarkCurve->l[end]; bl += (m_pMarkCurve->l[i] - bl) * 0.001; el -= (el - m_pMarkCurve->l[i]) * 0.001; if (begin == 0) begin = 0; else begin = pValue->FindIndex(m_pMarkCurve->x[begin], m_pMarkCurve->y[begin], -1); if (end == m_pMarkCurve->num - 1) end = pValue->num - 1; else end = pValue->FindIndex(m_pMarkCurve->x[end], m_pMarkCurve->y[end], -1); NewPointList.RemoveAll(); dfPoint dt; if (i == 0) { dt.x0 = dp.x0; dt.y0 = dp.y0; NewPointList.AddTail(dt); //使曲线光滑过渡 pValue->GetCoordinate(el, dt.x0, dt.y0, dt.z0); NewPointList.AddTail(dt); dt.x0 = m_pMarkCurve->x[ie]; dt.y0 = m_pMarkCurve->y[ie]; NewPointList.AddTail(dt); } else if (i == m_pMarkCurve->num - 1) { dt.x0 = m_pMarkCurve->x[ib]; dt.y0 = m_pMarkCurve->y[ib]; NewPointList.AddTail(dt); //使曲线光滑过渡 pValue->GetCoordinate(bl, dt.x0, dt.y0, dt.z0); NewPointList.AddTail(dt); dt.x0 = dp.x0; dt.y0 = dp.y0; NewPointList.AddTail(dt); } else { dt.x0 = m_pMarkCurve->x[ib]; dt.y0 = m_pMarkCurve->y[ib]; NewPointList.AddTail(dt); //使曲线光滑过渡 pValue->GetCoordinate(bl, dt.x0, dt.y0, dt.z0); NewPointList.AddTail(dt); dt.x0 = dp.x0; dt.y0 = dp.y0; NewPointList.AddTail(dt); //使曲线光滑过渡 pValue->GetCoordinate(el, dt.x0, dt.y0, dt.z0); NewPointList.AddTail(dt); dt.x0 = m_pMarkCurve->x[ie]; dt.y0 = m_pMarkCurve->y[ie]; NewPointList.AddTail(dt); } CCurveEx cu; cu.SetPoints(NewPointList, 2); NewPointList.RemoveAll(); cu.CurveToSpline(NewPointList, GetDC()->GetMiniSmoothStep() * 3, 0); } int CItemCurveEdit::GetOffsetMode(void) { //return ::GetPreferences().WorkaroundEdit.m_nOffsetMode; return GetDoc()->GetEditLineStatus() % 4; //return 9; } void CItemCurveEdit::DrawHandle(CXyDC* pDC, double x0, double y0) { CPen pen(PS_SOLID, 0, DRAG_LINE_COLOR); CPen* op = (CPen*)pDC->GetDC()->SelectObject(&pen); int od = pDC->GetDC()->SetROP2(R2_NOTXORPEN); pDC->GetDC()->SetROP2(od); pDC->GetDC()->SelectObject(op); } }//namespace