|
|
|
|
|
#include "StdAfx.h"
|
|
|
|
|
|
#include "CurveEditorDefault.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"
|
|
|
|
|
|
#include "SegmentSnappingEngine.h"
|
|
|
|
|
|
#include "Util.h"
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::OnDraw(CXyDC* pDC)
|
|
|
|
|
|
{
|
|
|
|
|
|
POSITION pos = GetPos();
|
|
|
|
|
|
if (pos == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>չ<EFBFBD><D5B9>
|
|
|
|
|
|
CCurveEx* pCurve = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::DrawAssistant(CDC* pDC, int mouseX, int mouseY)
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pCurve = GetControlCurve();
|
|
|
|
|
|
if (pCurve == nullptr) return;
|
|
|
|
|
|
|
|
|
|
|
|
m_handleDrawer->Init(pCurve);
|
|
|
|
|
|
m_handleDrawer->DrawAll(pDC);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::OnLButtonDown(CDC* pDC, UINT nFlags, CPoint point, int vk)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetScreenDC(pDC);
|
|
|
|
|
|
|
|
|
|
|
|
m_nDragSegmentIndex = -1; // <20><><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>϶<EFBFBD><CFB6><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>飺<EFBFBD><E9A3BA><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ѡ<EFBFBD>нڵ㣬<DAB5><E3A3AC><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><CFB6>߶<EFBFBD>
|
|
|
|
|
|
if (this->GetHandleIndex() < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>϶<EFBFBD>ģʽ
|
|
|
|
|
|
if (GetDoc()->GetEditLineStatus() == CURVE_STATE_DRAG_SEGMENT)
|
|
|
|
|
|
{
|
|
|
|
|
|
int segIndex = HitTestSegment(point);
|
|
|
|
|
|
if (segIndex >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>϶<EFBFBD>ģʽ
|
|
|
|
|
|
m_nDragSegmentIndex = segIndex;
|
|
|
|
|
|
m_nLButtonDownPoint = point;
|
|
|
|
|
|
|
|
|
|
|
|
c_down = GetDC()->GetReal(point);
|
|
|
|
|
|
c_last = c_down;
|
|
|
|
|
|
|
|
|
|
|
|
DrawMoveSegment(pDC); // <20><><EFBFBD>Ƴ<EFBFBD>ʼ״̬
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!IsCanAddHandle(point))
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ϴε<CFB4><CEB5><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>б<EFBFBD>
|
|
|
|
|
|
if (NewPointList.GetCount() > 0)
|
|
|
|
|
|
NewPointList.RemoveAll();
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>¼<EFBFBD><C2BC><EFBFBD>갴<EFBFBD><EAB0B4>λ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>꣩
|
|
|
|
|
|
m_nLButtonDownPoint = point;
|
|
|
|
|
|
c_down = GetDC()->GetReal(point);
|
|
|
|
|
|
c_last = c_down;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD>㣺<EFBFBD><E3A3BA><EFBFBD><EFBFBD>Ԥ<EFBFBD><D4A4>
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::OnMouseMove(CDC* dc, UINT nFlags, CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetScreenDC(dc);
|
|
|
|
|
|
|
|
|
|
|
|
POSITION pos = GetPos();
|
|
|
|
|
|
if (pos == 0)
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
|
|
CXyDC* pDC = GetDC();
|
|
|
|
|
|
|
|
|
|
|
|
if (IsDragging(nFlags)) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
{
|
|
|
|
|
|
HandleMouseDrag(pDC, point);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
HandleMouseHover(dc, point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_handleDrawer->DrawFocusHandle(dc, GetHandleIndex());
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::OnLButtonUp(CDC* pDC, UINT nFlags, CPoint point, int vk)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetScreenDC(pDC);
|
|
|
|
|
|
|
|
|
|
|
|
if (m_bLButtonDownWhenMouseMove == false)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
m_bLButtonDownWhenMouseMove = false;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>϶<EFBFBD><CFB6><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (m_nDragSegmentIndex >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. [<5B><><EFBFBD><EFBFBD>] ʹ<><CAB9><EFBFBD><EFBFBD>һ<EFBFBD>ε<EFBFBD> c_last <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD>Ӱ
|
|
|
|
|
|
DrawMoveSegment(pDC);
|
|
|
|
|
|
|
|
|
|
|
|
NBase::CPoint2D rawMouse = GetDC()->GetReal(point);
|
|
|
|
|
|
c_last = CalculateSnappedMousePos(rawMouse, m_nDragSegmentIndex);
|
|
|
|
|
|
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
int i = m_nDragSegmentIndex;
|
|
|
|
|
|
// <20><>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (i < 0 || i >= pValue->num - 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_nDragSegmentIndex = -1;
|
|
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3. [Undo/Redo <><D7BC>]
|
|
|
|
|
|
CActionCurveEdit* pAction = new CActionCurveEdit(GetDoc(), 0, GetPos());
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>ǰ<EFBFBD>Ľڵ<C4BD>λ<EFBFBD><CEBB>
|
|
|
|
|
|
pAction->BackupUndoNode(i, pValue->x[i], pValue->y[i]);
|
|
|
|
|
|
pAction->BackupUndoNode(i + 1, pValue->x[i + 1], pValue->y[i + 1]);
|
|
|
|
|
|
|
|
|
|
|
|
if (m_lastSnapResult.snapType == Geometry::SnapType::PARALLEL_LINE)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> A<><41>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -> ǿ<>ƹ<EFBFBD><C6B9><EFBFBD> (Projection)
|
|
|
|
|
|
const Geometry::Segment& targetSeg = m_lastSnapResult.targetSegment;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>쵱ǰ<ECB5B1><C7B0> (ת<><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
|
|
|
|
|
Geometry::Point pStart = { pValue->x[i], pValue->y[i] };
|
|
|
|
|
|
Geometry::Point pEnd = { pValue->x[i + 1], pValue->y[i + 1] };
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ͶӰ<CDB6><D3B0><EFBFBD><EFBFBD> t (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>߶<EFBFBD>)
|
|
|
|
|
|
double t1 = Geometry::GeometryUtils::getProjectionFactor(pStart, targetSeg);
|
|
|
|
|
|
double t2 = Geometry::GeometryUtils::getProjectionFactor(pEnd, targetSeg);
|
|
|
|
|
|
|
|
|
|
|
|
Geometry::Point dir = targetSeg.direction();
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ͶӰ<CDB6><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (Start + t * Dir)
|
|
|
|
|
|
Geometry::Point newStart = targetSeg.start + (dir * t1);
|
|
|
|
|
|
Geometry::Point newEnd = targetSeg.start + (dir * t2);
|
|
|
|
|
|
|
|
|
|
|
|
// ֱ<>Ӹ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>꣬<EFBFBD><EAA3AC><EFBFBD><EFBFBD>С<CEA2>ĽǶ<C4BD>ƫ<EFBFBD><C6AB>
|
|
|
|
|
|
pValue->x[i] = newStart.x;
|
|
|
|
|
|
pValue->y[i] = newStart.y;
|
|
|
|
|
|
pValue->x[i + 1] = newEnd.x;
|
|
|
|
|
|
pValue->y[i + 1] = newEnd.y;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> B<><42><EFBFBD><EFBFBD>ͨ<EFBFBD>ƶ<EFBFBD> -> <20><><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD> (Rigid Translation)
|
|
|
|
|
|
dfPoint pt1, pt2;
|
|
|
|
|
|
GetXY(pValue, i, pt1);
|
|
|
|
|
|
GetXY(pValue, i + 1, pt2);
|
|
|
|
|
|
|
|
|
|
|
|
double mouseDx = c_last.x0 - c_down.x0;
|
|
|
|
|
|
double mouseDy = c_last.y0 - c_down.y0;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ط<EFBFBD><D8B7>ߵ<EFBFBD>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>
|
|
|
|
|
|
NBase::CPoint2D offset = CalculateNormalOffset(pt1, pt2, mouseDx, mouseDy);
|
|
|
|
|
|
|
|
|
|
|
|
pValue->x[i] += offset.x0;
|
|
|
|
|
|
pValue->y[i] += offset.y0;
|
|
|
|
|
|
pValue->x[i + 1] += offset.x0;
|
|
|
|
|
|
pValue->y[i + 1] += offset.y0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (pValue->bAutoLocation)
|
|
|
|
|
|
pValue->GetLocation();
|
|
|
|
|
|
|
|
|
|
|
|
// 6. [Redo <20><>¼]
|
|
|
|
|
|
pAction->BackupRedoNode(i, pValue->x[i], pValue->y[i]);
|
|
|
|
|
|
pAction->BackupRedoNode(i + 1, pValue->x[i + 1], pValue->y[i + 1]);
|
|
|
|
|
|
GetDoc()->SetActionItem(pAction);
|
|
|
|
|
|
|
|
|
|
|
|
// 7. [<5B><>β<EFBFBD><CEB2><EFBFBD><EFBFBD>]
|
|
|
|
|
|
SetModifiedFlag(TRUE);
|
|
|
|
|
|
GetDoc()->Modified();
|
|
|
|
|
|
|
|
|
|
|
|
m_nDragSegmentIndex = -1;
|
|
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
|
|
|
|
|
|
// ˢ<><CBA2><EFBFBD><EFBFBD>ʾ
|
|
|
|
|
|
Invalidate();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
|
|
|
|
|
|
if (c_last == c_down)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// Ӧ<><D3A6><EFBFBD><EFBFBD>
|
|
|
|
|
|
OnCalculateDragEffect(nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
SetModifiedFlag(TRUE);
|
|
|
|
|
|
GetDoc()->Modified();
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::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 = GetControlCurve();
|
|
|
|
|
|
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();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorDefault::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
|
|
|
|
{
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorDefault::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (nChar)
|
|
|
|
|
|
{
|
|
|
|
|
|
case VK_ESCAPE:
|
|
|
|
|
|
if (!IsCaptureState()) break;
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
DrawSelectHandle(GetHandleIndex());
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorDefault::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (nChar)
|
|
|
|
|
|
{
|
|
|
|
|
|
case VK_ESCAPE:
|
|
|
|
|
|
EndEdit();
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::GetSubMenu()
|
|
|
|
|
|
{
|
|
|
|
|
|
return 6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::SetPos(POSITION pos)
|
|
|
|
|
|
{
|
|
|
|
|
|
CItem::SetPos(pos);
|
|
|
|
|
|
m_pBakOne.reset(); // <20><><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD><C9B1><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
if (pos)
|
|
|
|
|
|
{
|
|
|
|
|
|
COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos());
|
|
|
|
|
|
m_pBakOne = std::make_unique<COne>();
|
|
|
|
|
|
*m_pBakOne = *pOne;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>ù<EFBFBD><C3B9>ӣ<EFBFBD>ģʽ<C4A3>ض<EFBFBD><D8B6>ij<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>m_pMarkCurve<76><65>
|
|
|
|
|
|
OnModeInitialize();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::Clear(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pBakOne.reset(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::Draw(CDC* pDC)
|
|
|
|
|
|
{
|
|
|
|
|
|
POSITION pos = GetPos();
|
|
|
|
|
|
if (pos == 0) return;
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
DrawHandlesByCDC(pDC, pValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::GetNumberOfNode()
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pc = GetControlCurve();
|
|
|
|
|
|
if (pc == 0) return -1;
|
|
|
|
|
|
return pc->num;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::EreaseHandles(CDC* pDC)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_handleDrawer->ClearAll(pDC);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== <20>༭<EFBFBD>Ự<EFBFBD><E1BBB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫʵ<C8AB>֣<EFBFBD>==========
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::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);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (IsModified())
|
|
|
|
|
|
{
|
|
|
|
|
|
CActionItem* pAction = new CActionModifiedItem(GetDoc(), IDS_STRING_TOOLBAR_EDIT);
|
|
|
|
|
|
((CActionModifiedItem*)pAction)->BackupOldItem(GetPos(), m_pBakOne.get());
|
|
|
|
|
|
GetDoc()->SetActionItem(pAction);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::CancelAll(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pBakOne)
|
|
|
|
|
|
{
|
|
|
|
|
|
COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos());
|
|
|
|
|
|
*pOne = *m_pBakOne;
|
|
|
|
|
|
GetMarkCurve();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorDefault::IsCanCancelAll(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_pBakOne != nullptr ? TRUE : FALSE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::GetXY(CCurveEx* pValue, int nIndex, dfPoint& point)
|
|
|
|
|
|
{
|
|
|
|
|
|
pValue->GetPoint(nIndex, point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CCurveEx* CurveEditorDefault::GetControlCurve(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
POSITION pos = GetPos();
|
|
|
|
|
|
if (pos == nullptr) return nullptr;
|
|
|
|
|
|
return (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::HitTestHandle(CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
return HitTestHandle(GetControlCurve(), point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::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 CurveEditorDefault::IsDragging(int nFlags) const
|
|
|
|
|
|
{
|
|
|
|
|
|
return nFlags & 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::HandleMouseDrag(CXyDC* pDC, CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_bLButtonDownWhenMouseMove = true;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>϶<EFBFBD>
|
|
|
|
|
|
if (m_nDragSegmentIndex >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. [<5B><><EFBFBD><EFBFBD>]<5D><><EFBFBD><EFBFBD>ʱ c_last <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
DrawMoveSegment(GetScreenDC());
|
|
|
|
|
|
|
|
|
|
|
|
// 2. [<5B><><EFBFBD><EFBFBD>]<5D><><EFBFBD><EFBFBD> c_last <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>λ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>
|
|
|
|
|
|
NBase::CPoint2D rawMouse = GetDC()->GetReal(point);
|
|
|
|
|
|
c_last = CalculateSnappedMousePos(rawMouse, m_nDragSegmentIndex);
|
|
|
|
|
|
|
|
|
|
|
|
// 3. [<5B><><EFBFBD><EFBFBD>]<5D><>ʹ<EFBFBD><CAB9><EFBFBD>µ<EFBFBD> c_last <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
DrawMoveSegment(GetScreenDC());
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>û<EFBFBD><C3BB>ѡ<EFBFBD><D1A1><EFBFBD>ڵ㣬<DAB5><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ֻҪ<D6BB><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>ʱ<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ڵ<EFBFBD>
|
|
|
|
|
|
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);
|
|
|
|
|
|
c_down = GetDC()->GetReal(m_nLButtonDownPoint);
|
|
|
|
|
|
c_last = c_down;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>һ<EFBFBD>λ<EFBFBD><CEBB><EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ε<EFBFBD>Ԥ<EFBFBD><D4A4>
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
|
|
|
|
|
|
c_last = pDC->GetReal(point);
|
|
|
|
|
|
|
|
|
|
|
|
CPointList list;
|
|
|
|
|
|
OnCalculateDragEffect(&list);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>ʹ<EFBFBD>ø<EFBFBD><C3B8>º<EFBFBD><C2BA><EFBFBD> NewPointList<73><74>
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
CString str, string;
|
|
|
|
|
|
auto curve = std::make_unique<CCurveEx>();
|
|
|
|
|
|
curve->SetPoints(list, 2);
|
|
|
|
|
|
COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos());
|
|
|
|
|
|
CCurveEx* pValue = (CCurveEx*)pOne->GetValue();
|
|
|
|
|
|
|
|
|
|
|
|
OnDragMove(GetHandleIndex(), c_last);
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::HandleMouseHover(CDC* dc, CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>ʱ<EFBFBD>Ŀ<EFBFBD><C4BF>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::DeleteHandle(int nIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
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);
|
|
|
|
|
|
PointList.RemoveAll();
|
|
|
|
|
|
SetModifiedFlag(TRUE);
|
|
|
|
|
|
|
|
|
|
|
|
this->SetHandleIndex(-1);
|
|
|
|
|
|
|
|
|
|
|
|
if (bAttachProcess)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (oldPoints.GetCount() > 0)
|
|
|
|
|
|
AttachProcess(oldPoints, newPoints);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::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);
|
|
|
|
|
|
return AddHandle(pValue, add);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::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);
|
|
|
|
|
|
return nIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::AddHandle(CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
double l0;
|
|
|
|
|
|
if (!IsCanAddHandle(point, &l0)) return -1;
|
|
|
|
|
|
return AddHandle(l0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorDefault::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 CurveEditorDefault::AttachProcess(CPointList& oldPoints, CPointList& newPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::DrawMoveLine(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::GetMarkCurve(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CPoint2D CurveEditorDefault::GetCDown() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return c_down;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CPoint2D CurveEditorDefault::GetCLast() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return c_last;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::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++)
|
|
|
|
|
|
{
|
|
|
|
|
|
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);
|
|
|
|
|
|
ptPrev = point;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::DrawHandlesByCDC(CDC* pDC, CCurveEx* pCurve)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pCurve == nullptr) return;
|
|
|
|
|
|
m_handleDrawer->ClearAll(pDC);
|
|
|
|
|
|
m_handleDrawer->Init(pCurve);
|
|
|
|
|
|
m_handleDrawer->DrawAll(pDC);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::DrawSelectHandle(int nHandle)
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
if (pValue == nullptr) return;
|
|
|
|
|
|
if (nHandle < 0 || nHandle >= pValue->num) 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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CRect CurveEditorDefault::GetRangeWidthIndex(int nIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
if (pValue == nullptr || nIndex < 0 || nIndex >= pValue->num)
|
|
|
|
|
|
{
|
|
|
|
|
|
return CRect(0, 0, 0, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CRect CurveEditorDefault::GetFirstNodeHandleRectFocus(CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
CRect rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point);
|
|
|
|
|
|
rt.InflateRect(1, 1);
|
|
|
|
|
|
return rt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::SetDrawMode(int nModeX, int nModeY)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_nModeX = nModeX;
|
|
|
|
|
|
m_nModeY = nModeY;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::GetOffsetMode(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
return GetDoc()->GetEditLineStatus() % 4;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::OnDrawDragPreview()
|
|
|
|
|
|
{
|
|
|
|
|
|
// ========== Ĭ<><C4AC>ģʽ<C4A3><CABD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD> ==========
|
|
|
|
|
|
int i = GetHandleIndex();
|
|
|
|
|
|
if (i < 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
if (pValue == nullptr || i >= pValue->num)
|
|
|
|
|
|
{
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
double dx = c_last.x0 - c_down.x0;
|
|
|
|
|
|
double dy = c_last.y0 - c_down.y0;
|
|
|
|
|
|
dfPoint pt;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ǰһ<C7B0><D2BB><EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD>ǰ<EFBFBD>ڵ㵽ǰһ<C7B0><D2BB><EFBFBD>ڵ㣩
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>ƺ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD>ǰ<EFBFBD>ڵ㵽<DAB5><E3B5BD>һ<EFBFBD><D2BB><EFBFBD>ڵ㣩
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::OnCalculateDragEffect(CPointList* pList)
|
|
|
|
|
|
{
|
|
|
|
|
|
// pList != nullptr<74><72>Ԥ<EFBFBD><D4A4>ģʽ<C4A3><CABD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><DEB8><EFBFBD><EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>
|
|
|
|
|
|
// pList == nullptr<74><72>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Undo/Redo <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
BOOL bRedraw = TRUE;
|
|
|
|
|
|
BOOL bAttachProcess = TRUE; // <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
CCurveEx* pValue = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos());
|
|
|
|
|
|
|
|
|
|
|
|
if (pList)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Ԥ<><D4A4>ģʽ<C4A3><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
|
|
|
|
|
|
CCurveEx* pc = new CCurveEx;
|
|
|
|
|
|
*pc = *pValue;
|
|
|
|
|
|
pValue = pc;
|
|
|
|
|
|
bRedraw = FALSE;
|
|
|
|
|
|
bAttachProcess = FALSE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CPointList oldPoints; // <20><>¼<EFBFBD>ƶ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>꣨<EFBFBD><EAA3A8><EFBFBD>ڰ<DAB0><F3B6A8B4><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
CPointList newPoints; // <20><>¼<EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>꣨<EFBFBD><EAA3A8><EFBFBD>ڰ<DAB0><F3B6A8B4><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
dfPoint pt;
|
|
|
|
|
|
CRect rt;
|
|
|
|
|
|
|
|
|
|
|
|
// ========== Ĭ<><C4AC>ģʽ<C4A3><CABD>ֱ<EFBFBD><D6B1><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD>ǰ<EFBFBD>ڵ<EFBFBD> ==========
|
|
|
|
|
|
int i = GetHandleIndex();
|
|
|
|
|
|
if (bRedraw)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD> GetRangeWidthIndex<65><78><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>
|
|
|
|
|
|
// rt = GetRangeWidthIndex(i);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Ϊ<>˰<CBB0><F3B6A8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼ԭ<C2BC><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
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)
|
|
|
|
|
|
{
|
|
|
|
|
|
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)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Ϊ<>˰<CBB0><F3B6A8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (pList)
|
|
|
|
|
|
{
|
|
|
|
|
|
pValue->GetPoint(*pList);
|
|
|
|
|
|
delete pValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::OnModeInitialize()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Default implementation - does nothing
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::OnDragMove(int nIndex, CPoint2D pt)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Default implementation - does nothing
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== <20>߶<EFBFBD><DFB6>϶<EFBFBD><CFB6><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5> ==========
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorDefault::HitTestSegment(CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
if (!pValue || pValue->num < 2) return -1;
|
|
|
|
|
|
|
|
|
|
|
|
CXyDC* pDC = GetDC();
|
|
|
|
|
|
double distThreshold = 5.0; // ѡ<><D1A1><EFBFBD>ݲ<DDB2><EEA3A8><EFBFBD>أ<EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < pValue->num - 1; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><>ȡ<EFBFBD>߶<EFBFBD><DFB6><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD>
|
|
|
|
|
|
CPoint p1 = pDC->GetScreen(pValue->x[i], pValue->y[i]);
|
|
|
|
|
|
CPoint p2 = pDC->GetScreen(pValue->x[i + 1], pValue->y[i + 1]);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>㵽<EFBFBD>߶εľ<CEB5><C4BE><EFBFBD>
|
|
|
|
|
|
double dist = DistancePointToLine(point.x, point.y, p1.x, p1.y, p2.x, p2.y);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>жϷ<D0B6>Χ<EFBFBD><CEA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4>߶<EFBFBD>Ϊ<EFBFBD>Խ<EFBFBD><D4BD>ߵľ<DFB5><C4BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><CEA2><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD>Χ<EFBFBD><CEA7>
|
|
|
|
|
|
CRect rt(p1, p2);
|
|
|
|
|
|
rt.NormalizeRect();
|
|
|
|
|
|
rt.InflateRect((int)distThreshold + 2, (int)distThreshold + 2);
|
|
|
|
|
|
|
|
|
|
|
|
if (rt.PtInRect(point) && dist < distThreshold)
|
|
|
|
|
|
{
|
|
|
|
|
|
return i; // <20><><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorDefault::DrawMoveSegment(CDC* pDC)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. <20><><EFBFBD><EFBFBD>У<EFBFBD>飺<EFBFBD><E9A3BA><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><CFB6><EFBFBD><EFBFBD>߶Σ<DFB6>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
|
|
|
|
|
|
if (m_nDragSegmentIndex < 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
// У<><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><CEA7>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (m_nDragSegmentIndex >= pValue->num - 1) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 2. <20><>ȡԭʼ<D4AD>߶ε<DFB6><CEB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ȡ)
|
|
|
|
|
|
dfPoint pt1, pt2;
|
|
|
|
|
|
GetXY(pValue, m_nDragSegmentIndex, pt1);
|
|
|
|
|
|
GetXY(pValue, m_nDragSegmentIndex + 1, pt2);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB>Ƶ<EFBFBD><C6B5><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
double drawX1, drawY1, drawX2, drawY2;
|
|
|
|
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
|
|
// <20><><EFBFBD>ķ<EFBFBD>֧<EFBFBD><D6A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;<EFBFBD><CDBE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʋ<EFBFBD><C6B2><EFBFBD>
|
|
|
|
|
|
// ========================================================================
|
|
|
|
|
|
bool isSnapping = (m_lastSnapResult.snapType == Geometry::SnapType::PARALLEL_LINE);
|
|
|
|
|
|
if (isSnapping)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> A<><41>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -> ͶӰ<CDB6><D3B0>ʾ (Projection)
|
|
|
|
|
|
const Geometry::Segment& targetSeg = m_lastSnapResult.targetSegment;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>켸<EFBFBD>ε<EFBFBD>
|
|
|
|
|
|
Geometry::Point pStart = { pt1.x0, pt1.y0 };
|
|
|
|
|
|
Geometry::Point pEnd = { pt2.x0, pt2.y0 };
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ͶӰ<CDB6><D3B0><EFBFBD><EFBFBD> t (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>߶<EFBFBD>)
|
|
|
|
|
|
double t1 = Geometry::GeometryUtils::getProjectionFactor(pStart, targetSeg);
|
|
|
|
|
|
double t2 = Geometry::GeometryUtils::getProjectionFactor(pEnd, targetSeg);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>ȡĿ<C8A1><C4BF><EFBFBD>߶εķ<CEB5><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
Geometry::Point dir = targetSeg.direction();
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ͶӰ<CDB6><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
Geometry::Point newStart = targetSeg.start + (dir * t1);
|
|
|
|
|
|
Geometry::Point newEnd = targetSeg.start + (dir * t2);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>Ʊ<EFBFBD><C6B1><EFBFBD>
|
|
|
|
|
|
drawX1 = newStart.x;
|
|
|
|
|
|
drawY1 = newStart.y;
|
|
|
|
|
|
drawX2 = newEnd.x;
|
|
|
|
|
|
drawY2 = newEnd.y;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> B<><42><EFBFBD><EFBFBD>ͨ<EFBFBD>ƶ<EFBFBD> -> <20><><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD> (Rigid Translation)
|
|
|
|
|
|
double mouseDx = c_last.x0 - c_down.x0;
|
|
|
|
|
|
double mouseDy = c_last.y0 - c_down.y0;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ط<EFBFBD><D8B7>ߵ<EFBFBD>ͶӰƫ<D3B0><C6AB><EFBFBD><EFBFBD>
|
|
|
|
|
|
NBase::CPoint2D offset = CalculateNormalOffset(pt1, pt2, mouseDx, mouseDy);
|
|
|
|
|
|
|
|
|
|
|
|
// ԭʼ<D4AD><CABC><EFBFBD><EFBFBD> + ƫ<><C6AB><EFBFBD><EFBFBD> = <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
drawX1 = pt1.x0 + offset.x0;
|
|
|
|
|
|
drawY1 = pt1.y0 + offset.y0;
|
|
|
|
|
|
drawX2 = pt2.x0 + offset.x0;
|
|
|
|
|
|
drawY2 = pt2.y0 + offset.y0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
|
|
// <20><>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD> (XOR ģʽ)
|
|
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>
|
|
|
|
|
|
CXyDC* pXyDC = GetDC();
|
|
|
|
|
|
|
|
|
|
|
|
COLORREF penColor = isSnapping ? RGB(255, 0, 0) : DRAG_LINE_COLOR;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>û<EFBFBD><C3BB>ʣ<EFBFBD>ʵ<EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD>ɫ<EFBFBD><C9AB> DRAG_LINE_COLOR <20><><EFBFBD><EFBFBD>
|
|
|
|
|
|
CPen pen(PS_SOLID, 0, penColor);
|
|
|
|
|
|
CPen* op = m_pScreenDC->SelectObject(&pen);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>û<EFBFBD>ͼģʽΪ R2_NOTXORPEN (<28><><EFBFBD><EFBFBD>ģʽ)
|
|
|
|
|
|
int od = m_pScreenDC->SetROP2(R2_NOTXORPEN);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD><CEAA>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
CPoint sp1 = pXyDC->GetScreen(drawX1, drawY1);
|
|
|
|
|
|
CPoint sp2 = pXyDC->GetScreen(drawX2, drawY2);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
m_pScreenDC->MoveTo(sp1);
|
|
|
|
|
|
m_pScreenDC->LineTo(sp2);
|
|
|
|
|
|
|
|
|
|
|
|
// <20>ָ<EFBFBD><D6B8><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD>
|
|
|
|
|
|
m_pScreenDC->SetROP2(od);
|
|
|
|
|
|
m_pScreenDC->SelectObject(op);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NBase::CPoint2D CurveEditorDefault::CalculateNormalOffset(dfPoint p1, dfPoint p2, double dx, double dy)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
double segX = p2.x0 - p1.x0;
|
|
|
|
|
|
double segY = p2.y0 - p1.y0;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (-y, x)
|
|
|
|
|
|
double normX = -segY;
|
|
|
|
|
|
double normY = segX;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>һ<EFBFBD><D2BB>
|
|
|
|
|
|
double len = sqrt(normX * normX + normY * normY);
|
|
|
|
|
|
if (len < 1e-9) return { 0.0, 0.0 };
|
|
|
|
|
|
normX /= len;
|
|
|
|
|
|
normY /= len;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ͶӰ<CDB6><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD>ϵij<CFB5><C4B3><EFBFBD>
|
|
|
|
|
|
double projection = dx * normX + dy * normY;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
return { projection * normX, projection * normY };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double CurveEditorDefault::DistancePointToLine(double px, double py, double x1, double y1, double x2, double y2)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20>߶γ<DFB6><CEB3>ȵ<EFBFBD>ƽ<EFBFBD><C6BD>
|
|
|
|
|
|
double l2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>߶γ<DFB6><CEB3><EFBFBD>Ϊ0<CEAA><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5>غϣ<D8BA><CFA3><EFBFBD>ֱ<EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD>㵽<EFBFBD><E3B5BD><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD>
|
|
|
|
|
|
if (l2 == 0.0)
|
|
|
|
|
|
return sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ͶӰ<CDB6><D3B0><EFBFBD><EFBFBD> t = ((P - A) . (B - A)) / |B - A|^2
|
|
|
|
|
|
double t = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / l2;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> t <20><> [0, 1] <20><>Χ<EFBFBD>ڣ<EFBFBD><DAA3>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD>
|
|
|
|
|
|
if (t < 0.0) t = 0.0;
|
|
|
|
|
|
else if (t > 1.0) t = 1.0;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͶӰ<CDB6><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
double projX = x1 + t * (x2 - x1);
|
|
|
|
|
|
double projY = y1 + t * (y2 - y1);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>ص㵽ͶӰ<CDB6><D3B0><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><C3BE><EFBFBD>
|
|
|
|
|
|
return sqrt((px - projX) * (px - projX) + (py - projY) * (py - projY));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CRect8 CurveEditorDefault::GetLineSegmentAABB(const dfPoint& point1, const dfPoint& point2, double width) const
|
|
|
|
|
|
{
|
|
|
|
|
|
double halfWidth = width / 2.0;
|
|
|
|
|
|
double rawMinX = min(point1.x0, point2.x0);
|
|
|
|
|
|
double rawMaxX = max(point1.x0, point2.x0);
|
|
|
|
|
|
double rawMinY = min(point1.y0, point2.y0);
|
|
|
|
|
|
double rawMaxY = max(point1.y0, point2.y0);
|
|
|
|
|
|
|
|
|
|
|
|
return CRect8(rawMinX - halfWidth, rawMaxY + halfWidth, rawMaxX + halfWidth, rawMinY - halfWidth);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NBase::CPoint2D CurveEditorDefault::CalculateSnappedMousePos(NBase::CPoint2D rawMouse, int segmentIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!GetDoc()->IsSnapEnabled())
|
|
|
|
|
|
{
|
|
|
|
|
|
return rawMouse;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
if (!pValue || segmentIndex < 0 || segmentIndex >= pValue->num - 1)
|
|
|
|
|
|
return rawMouse;
|
|
|
|
|
|
|
|
|
|
|
|
// 1. <><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
dfPoint pt1, pt2;
|
|
|
|
|
|
GetXY(pValue, segmentIndex, pt1);
|
|
|
|
|
|
GetXY(pValue, segmentIndex + 1, pt2);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>㵱ǰ<E3B5B1>߶εĵ<CEB5>λ<EFBFBD><CEBB><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD>)
|
|
|
|
|
|
double segDx = pt2.x0 - pt1.x0;
|
|
|
|
|
|
double segDy = pt2.y0 - pt1.y0;
|
|
|
|
|
|
double nx = -segDy;
|
|
|
|
|
|
double ny = segDx;
|
|
|
|
|
|
double len = std::hypot(nx, ny);
|
|
|
|
|
|
if (len < 1e-9) return rawMouse;
|
|
|
|
|
|
nx /= len;
|
|
|
|
|
|
ny /= len;
|
|
|
|
|
|
|
|
|
|
|
|
// 2. <20><><EFBFBD><EFBFBD>"<22><><EFBFBD><EFBFBD>"<22>߶<EFBFBD>λ<EFBFBD><CEBB>
|
|
|
|
|
|
double mouseDx = rawMouse.x0 - c_down.x0;
|
|
|
|
|
|
double mouseDy = rawMouse.y0 - c_down.y0;
|
|
|
|
|
|
double projLen = mouseDx * nx + mouseDy * ny;
|
|
|
|
|
|
NBase::CPoint2D normalOffset = { projLen * nx, projLen * ny };
|
|
|
|
|
|
|
|
|
|
|
|
Geometry::Segment currentSeg;
|
|
|
|
|
|
currentSeg.start = { pt1.x0 + normalOffset.x0, pt1.y0 + normalOffset.y0 };
|
|
|
|
|
|
currentSeg.end = { pt2.x0 + normalOffset.x0, pt2.y0 + normalOffset.y0 };
|
|
|
|
|
|
|
|
|
|
|
|
// 3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD>ӿڣ<D3BF><DAA3><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
|
|
|
|
|
Geometry::SnapConfig config;
|
|
|
|
|
|
config.snapDistance = GetDC()->GetRealWidth(20.0);
|
|
|
|
|
|
config.angleTolerance = 5.0;
|
|
|
|
|
|
Geometry::SnappingEngine engine(GetDoc()->m_pXy, GetSpatialIndex(), config);
|
|
|
|
|
|
|
|
|
|
|
|
Geometry::SnapResult res = engine.getSnapResult(currentSeg);
|
|
|
|
|
|
|
|
|
|
|
|
m_lastSnapResult = res;
|
|
|
|
|
|
|
|
|
|
|
|
// 4. <20>༭<EFBFBD><E0BCAD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD><C4BA>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㹲<EFBFBD>߲<EFBFBD><DFB2><EFBFBD>
|
|
|
|
|
|
if (res.snapType != Geometry::SnapType::NONE)
|
|
|
|
|
|
{
|
|
|
|
|
|
double finalOffsetX = res.offset.x;
|
|
|
|
|
|
double finalOffsetY = res.offset.y;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>Ķ<EFBFBD><C4B6>㡿<EFBFBD><E3A1BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>Ŀ<EFBFBD><C4BF><EFBFBD>߶μ<DFB6><CEBC>㽻<EFBFBD><E3BDBB>
|
|
|
|
|
|
if (res.snapType == Geometry::SnapType::PARALLEL_LINE)
|
|
|
|
|
|
{
|
|
|
|
|
|
// P_target
|
|
|
|
|
|
double tx = res.targetSegment.start.x;
|
|
|
|
|
|
double ty = res.targetSegment.start.y;
|
|
|
|
|
|
// Target Direction (V)
|
|
|
|
|
|
double vx = res.targetSegment.end.x - tx;
|
|
|
|
|
|
double vy = res.targetSegment.end.y - ty;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ⷽ<EFBFBD><E2B7BD>:
|
|
|
|
|
|
// CurrentStart + t * Normal = TargetStart + u * TargetDir
|
|
|
|
|
|
// <20><><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
double dx = currentSeg.start.x - tx;
|
|
|
|
|
|
double dy = currentSeg.start.y - ty;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>ά<EFBFBD><CEAC><EFBFBD><EFBFBD>: A cross B = Ax * By - Ay * Bx
|
|
|
|
|
|
double det = nx * vy - ny * vx;
|
|
|
|
|
|
|
|
|
|
|
|
// ֻҪ det != 0 (<28><><EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ߣ<EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>˵ԭ<CBB5>߶β<DFB6><CEB2><EFBFBD>ֱ<EFBFBD><D6B1>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>)
|
|
|
|
|
|
if (std::abs(det) > 1e-9)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD> (Cramer's Rule) <20><> t (<28>ط<EFBFBD><D8B7><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6>ľ<EFBFBD><C4BE><EFBFBD>)
|
|
|
|
|
|
double t = (vx * dy - vy * dx) / det;
|
|
|
|
|
|
|
|
|
|
|
|
finalOffsetX = nx * t;
|
|
|
|
|
|
finalOffsetY = ny * t;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
rawMouse.x0 += finalOffsetX;
|
|
|
|
|
|
rawMouse.y0 += finalOffsetY;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return rawMouse;
|
|
|
|
|
|
}
|