You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1371 lines
30 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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<CActionModifiedItem> pAction = std::make_unique<CActionModifiedItem>(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);
//<temp> //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);
}
}
//</temp>
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