|
|
#include "StdAfx.h"
|
|
|
#include "itemcurvearc.h"
|
|
|
#include "SigmaDoc.h"
|
|
|
|
|
|
namespace NItem
|
|
|
{
|
|
|
static CRect CalculateHandleRect(LPPOINT pPoint);
|
|
|
|
|
|
CItemCurveArc::CItemCurveArc(CSigmaDoc * ppDoc)
|
|
|
: CItemCurve(ppDoc)
|
|
|
, loop(0)
|
|
|
{
|
|
|
m_AddLineState = ppDoc->GetEditLineStatus();
|
|
|
m_pArc = new CItemArc(ppDoc);
|
|
|
m_pArc->m_bDoSelectEnd = FALSE;
|
|
|
}
|
|
|
|
|
|
CItemCurveArc::~CItemCurveArc(void)
|
|
|
{
|
|
|
if (m_pArc)delete m_pArc;
|
|
|
m_pArc = NULL;
|
|
|
}
|
|
|
|
|
|
BOOL CItemCurveArc::IsArcState(void)
|
|
|
{
|
|
|
if (m_AddLineState != CURVE_STATE_ARC)
|
|
|
return FALSE;
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
void CItemCurveArc::OnLButtonDown(CDC *pDC, UINT nFlags, CPoint point, int vk)
|
|
|
{
|
|
|
if (!IsArcState())
|
|
|
CItemCurve::OnLButtonDown(pDC, nFlags, point, vk);
|
|
|
else
|
|
|
{
|
|
|
ClearRedoList();
|
|
|
m_pArc->OnLButtonDown(pDC, nFlags, point, vk);
|
|
|
|
|
|
if (loop == 2)
|
|
|
{
|
|
|
CArc* pArc = m_pArc->CreateArc();
|
|
|
if (pArc == NULL) return;
|
|
|
|
|
|
CCurveEx* pCurve = pArc->GetCurve();
|
|
|
dfPoint pt;
|
|
|
m_dpLastMousePos.x0 = m_pArc->PointStart.x0; m_dpLastMousePos.y0 = m_pArc->PointStart.y0;
|
|
|
for (int i = 0; i < pCurve->num; i++)
|
|
|
{
|
|
|
pt.x0 = pCurve->x[i];
|
|
|
pt.y0 = pCurve->y[i];
|
|
|
DrawLineScreen(m_dpLastMousePos.x0, m_dpLastMousePos.y0, pt.x0, pt.y0);
|
|
|
AddPoint(pt);
|
|
|
m_dpLastMousePos = pt;
|
|
|
}
|
|
|
delete pArc;
|
|
|
|
|
|
m_pArc->PointStart = m_pArc->PointEnd;
|
|
|
m_pArc->PointMiddle = m_pArc->PointStart;
|
|
|
m_pArc->loop = 1;
|
|
|
loop = 0;
|
|
|
}
|
|
|
loop++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int CItemCurveArc::OnMouseMove(CDC* pDC, UINT nFlags, CPoint point)//, BYTE*& destBuffer, int& destLen)
|
|
|
{
|
|
|
if (!IsArcState())
|
|
|
{
|
|
|
return CItemCurve::OnMouseMove(pDC, nFlags, point);//, destBuffer, destLen);
|
|
|
}
|
|
|
else if (m_pArc)
|
|
|
{
|
|
|
if (m_pArc->loop == 1)
|
|
|
{
|
|
|
if (!PointList.IsEmpty())
|
|
|
m_pArc->PointStart = PointList.GetTail();
|
|
|
}
|
|
|
m_dpLastMousePos = GetRealPoint(PointList, nFlags, point);
|
|
|
|
|
|
return m_pArc->OnMouseMove(pDC, nFlags, point);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void CItemCurveArc::OnLButtonUp(CDC *pDC, UINT nFlags, CPoint point, int vk)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
void CItemCurveArc::SetCurveState(int state, CDC * pDC)
|
|
|
{
|
|
|
if (m_AddLineState == state) return;
|
|
|
CItemCurve::SetCurveState(state, pDC);
|
|
|
if (m_AddLineState == CURVE_STATE_ARC && PointList.GetCount() > 0)
|
|
|
{
|
|
|
m_pArc->PointStart = PointList.GetTail();
|
|
|
m_pArc->PointMiddle = m_pArc->PointStart;
|
|
|
loop = 1;
|
|
|
m_pArc->loop = loop;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
CItemCurveSpline::CItemCurveSpline(CSigmaDoc * ppDoc)
|
|
|
: CItemCurveArc(ppDoc)
|
|
|
{
|
|
|
m_nSplineNodes = 5;
|
|
|
m_mSmoothStepFactor = 3;
|
|
|
}
|
|
|
|
|
|
CItemCurveSpline::~CItemCurveSpline(void)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::OnDraw(CXyDC* pDC)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::DrawSplineCurve(CXyDC* pDC, const CPointList& controlPoints)
|
|
|
{
|
|
|
if (controlPoints.GetCount() <= 1)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Build spline curve from control points
|
|
|
CPointList sampledPoints;
|
|
|
BuildSplineCurve(controlPoints, sampledPoints);
|
|
|
if (sampledPoints.GetCount() <= 1)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Draw the curve
|
|
|
CDC* pdc = pDC->GetDC();
|
|
|
HDC hdc = pdc->m_hDC;
|
|
|
CPen* pOld = pdc->SelectObject(&m_pen);
|
|
|
|
|
|
POSITION pos = sampledPoints.GetHeadPosition();
|
|
|
dfPoint dp = sampledPoints.GetNext(pos);
|
|
|
CPoint pt1 = pDC->GetScreen(dp.x0, dp.y0);
|
|
|
CPoint pt2;
|
|
|
POINT prePt;
|
|
|
|
|
|
while (pos)
|
|
|
{
|
|
|
dp = sampledPoints.GetNext(pos);
|
|
|
pt2 = pDC->GetScreen(dp.x0, dp.y0);
|
|
|
::MoveToEx(hdc, pt1.x, pt1.y, &prePt);
|
|
|
::LineTo(hdc, pt2.x, pt2.y);
|
|
|
pt1 = pt2;
|
|
|
}
|
|
|
|
|
|
pdc->SelectObject(pOld);
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::DrawControlPointHandles(CXyDC* pDC, const CPointList& controlPoints)
|
|
|
{
|
|
|
if (controlPoints.GetCount() == 0)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
CDC* pdc = pDC->GetDC();
|
|
|
CPen pen;
|
|
|
pen.CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
|
|
|
CPen* pOld = pdc->SelectObject(&pen);
|
|
|
|
|
|
dfPoint prevPoint;
|
|
|
BOOL hasPrev = FALSE;
|
|
|
POSITION pos = controlPoints.GetHeadPosition();
|
|
|
|
|
|
while (pos)
|
|
|
{
|
|
|
dfPoint dp = controlPoints.GetNext(pos);
|
|
|
|
|
|
// Skip duplicate points
|
|
|
if (hasPrev && fabs(prevPoint.x0 - dp.x0) < 1e-3 && fabs(prevPoint.y0 - dp.y0) < 1e-3)
|
|
|
continue;
|
|
|
|
|
|
CPoint sp = pDC->GetScreen(dp.x0, dp.y0);
|
|
|
CRect rt = CalculateHandleRect(&sp);
|
|
|
rt.InflateRect(1, 1);
|
|
|
pdc->Ellipse(&rt);
|
|
|
|
|
|
prevPoint = dp;
|
|
|
hasPrev = TRUE;
|
|
|
}
|
|
|
|
|
|
pdc->SelectObject(pOld);
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::BuildSplineCurve(const CPointList& controlPoints, CPointList& outSampledPoints)
|
|
|
{
|
|
|
outSampledPoints.RemoveAll();
|
|
|
if (controlPoints.GetCount() <= 1)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
CCurveEx ce;
|
|
|
ce.SetPoints(const_cast<CPointList&>(controlPoints), 2);
|
|
|
ce.CurveToSpline(outSampledPoints, GetDC()->GetMiniSmoothStep() * m_mSmoothStepFactor, 0);
|
|
|
}
|
|
|
|
|
|
size_t CItemCurveSpline::FindCommonPrefixLength(const std::vector<CPoint>& oldPoints,
|
|
|
const std::vector<CPoint>& newPoints)
|
|
|
{
|
|
|
size_t commonCount = 0;
|
|
|
size_t minSize = (oldPoints.size() < newPoints.size())
|
|
|
? oldPoints.size() : newPoints.size();
|
|
|
|
|
|
for (size_t i = 0; i < minSize; i++)
|
|
|
{
|
|
|
if (oldPoints[i] == newPoints[i])
|
|
|
commonCount++;
|
|
|
else
|
|
|
break;
|
|
|
}
|
|
|
return commonCount;
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::DrawPolylineXOR(CDC* pDC, const std::vector<CPoint>& points, size_t startIdx)
|
|
|
{
|
|
|
for (size_t i = startIdx; i + 1 < points.size(); i++)
|
|
|
{
|
|
|
pDC->MoveTo(points[i]);
|
|
|
pDC->LineTo(points[i + 1]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::IncrementalUpdatePreview(CDC* pScreenDC, const std::vector<CPoint>& newScreenPoints)
|
|
|
{
|
|
|
size_t commonCount = FindCommonPrefixLength(m_cachedScreenPoints, newScreenPoints);
|
|
|
|
|
|
// Setup XOR drawing mode
|
|
|
int od = pScreenDC->SetROP2(R2_NOTXORPEN);
|
|
|
CPen* pOld = pScreenDC->SelectObject(&m_pen);
|
|
|
|
|
|
// Erase old different segments
|
|
|
if (commonCount < m_cachedScreenPoints.size())
|
|
|
{
|
|
|
// Start from commonCount-1 to ensure continuity, but don't go below 0
|
|
|
size_t startIdx = (commonCount > 0) ? commonCount - 1 : 0;
|
|
|
DrawPolylineXOR(pScreenDC, m_cachedScreenPoints, startIdx);
|
|
|
}
|
|
|
|
|
|
// Draw new different segments
|
|
|
if (commonCount < newScreenPoints.size())
|
|
|
{
|
|
|
// Start from commonCount-1 to ensure continuity, but don't go below 0
|
|
|
size_t startIdx = (commonCount > 0) ? commonCount - 1 : 0;
|
|
|
DrawPolylineXOR(pScreenDC, newScreenPoints, startIdx);
|
|
|
}
|
|
|
|
|
|
// Restore
|
|
|
pScreenDC->SelectObject(pOld);
|
|
|
pScreenDC->SetROP2(od);
|
|
|
|
|
|
// Update cache
|
|
|
m_cachedScreenPoints = newScreenPoints;
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::ErasePreview(CDC* pScreenDC)
|
|
|
{
|
|
|
if (pScreenDC == 0 || m_cachedScreenPoints.size() <= 1)
|
|
|
return;
|
|
|
|
|
|
// Use XOR to erase using exact cached screen coordinates
|
|
|
int od = pScreenDC->SetROP2(R2_NOTXORPEN);
|
|
|
CPen* pOld = pScreenDC->SelectObject(&m_pen);
|
|
|
|
|
|
for (size_t i = 0; i + 1 < m_cachedScreenPoints.size(); i++)
|
|
|
{
|
|
|
pScreenDC->MoveTo(m_cachedScreenPoints[i]);
|
|
|
pScreenDC->LineTo(m_cachedScreenPoints[i + 1]);
|
|
|
}
|
|
|
|
|
|
pScreenDC->SelectObject(pOld);
|
|
|
pScreenDC->SetROP2(od);
|
|
|
|
|
|
m_cachedScreenPoints.clear();
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::DrawPreview(CDC* pScreenDC)
|
|
|
{
|
|
|
if (pScreenDC == 0 || m_controlPoints.GetCount() == 0)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Build preview control points (existing + current mouse position)
|
|
|
CPointList previewControlPoints;
|
|
|
POSITION pos = m_controlPoints.GetHeadPosition();
|
|
|
while (pos)
|
|
|
{
|
|
|
previewControlPoints.AddTail(m_controlPoints.GetNext(pos));
|
|
|
}
|
|
|
previewControlPoints.AddTail(m_dpLastMousePos);
|
|
|
|
|
|
if (previewControlPoints.GetCount() <= 1)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Build spline curve
|
|
|
CPointList sampledPoints;
|
|
|
BuildSplineCurve(previewControlPoints, sampledPoints);
|
|
|
if (sampledPoints.GetCount() <= 1)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Convert to screen points
|
|
|
CXyDC* pDC = GetDC();
|
|
|
if (pDC == 0)
|
|
|
return;
|
|
|
pDC->Create(pScreenDC);
|
|
|
|
|
|
std::vector<CPoint> newScreenPoints;
|
|
|
pos = sampledPoints.GetHeadPosition();
|
|
|
while (pos)
|
|
|
{
|
|
|
dfPoint dp = sampledPoints.GetNext(pos);
|
|
|
CPoint pt = pDC->GetScreen(dp.x0, dp.y0);
|
|
|
newScreenPoints.push_back(pt);
|
|
|
}
|
|
|
|
|
|
if (newScreenPoints.size() < 2)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Incremental update using XOR diff
|
|
|
IncrementalUpdatePreview(pScreenDC, newScreenPoints);
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::DrawControlPointHandles(CDC * pDC)
|
|
|
{
|
|
|
if (m_controlPoints.GetCount() > 0)
|
|
|
{
|
|
|
CXyDC* pXyDC = GetDC();
|
|
|
if (pXyDC)
|
|
|
{
|
|
|
pXyDC->Create(pDC);
|
|
|
DrawControlPointHandles(pXyDC, m_controlPoints);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::OnLButtonDown(CDC *pDC, UINT nFlags, CPoint point, int vk)
|
|
|
{
|
|
|
if (!IsSplineState())
|
|
|
{
|
|
|
CItemCurveArc::OnLButtonDown(pDC, nFlags, point, vk);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
ClearRedoList();
|
|
|
dfPoint dp = GetRealPoint(m_controlPoints, nFlags, point);
|
|
|
|
|
|
// Add control point
|
|
|
m_controlPoints.AddTail(dp);
|
|
|
|
|
|
TRACE("m_controlPoints.Count = %d\n", m_controlPoints.GetCount());
|
|
|
|
|
|
m_bStretchStart = TRUE;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CItemCurveSpline::OnMouseMove(CDC* pDC, UINT nFlags, CPoint point)
|
|
|
{
|
|
|
m_pScreenDC = pDC;
|
|
|
if (m_controlPoints.GetCount() == 0)
|
|
|
{
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
// Update preview point
|
|
|
dfPoint dp = GetRealPoint(m_controlPoints, nFlags, point);
|
|
|
|
|
|
// Update mouse position
|
|
|
m_dpLastMousePos = dp;
|
|
|
|
|
|
// Draw new preview (with incremental diff update)
|
|
|
DrawPreview(pDC);
|
|
|
|
|
|
DrawControlPointHandles(pDC);
|
|
|
|
|
|
m_bStretchStart = FALSE;
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::OnLButtonUp(CDC *pDC, UINT nFlags, CPoint point, int vk)
|
|
|
{
|
|
|
if (!IsSplineState())
|
|
|
{
|
|
|
CItemCurveArc::OnLButtonUp(pDC, nFlags, point, vk);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::SetCurveState(int state, CDC * pDC)
|
|
|
{
|
|
|
if (state == m_AddLineState)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (m_AddLineState == CURVE_STATE_SPLINE)
|
|
|
{
|
|
|
AppendPoint(); // Finalize current spline
|
|
|
}
|
|
|
|
|
|
if (state == CURVE_STATE_SPLINE)
|
|
|
{
|
|
|
m_controlPoints.RemoveAll();
|
|
|
if (PointList.GetCount() > 0)
|
|
|
{
|
|
|
dfPoint dp = PointList.GetTail();
|
|
|
m_controlPoints.AddTail(dp); // Start new spline from last point
|
|
|
if (!m_bStretchStart)
|
|
|
{
|
|
|
EraseRubberLine();
|
|
|
DrawPreview(pDC);
|
|
|
m_bStretchStart = true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
CItemCurveArc::SetCurveState(state, pDC);
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::AutoClose(void)
|
|
|
{
|
|
|
AppendPoint();
|
|
|
CItemCurveArc::AutoClose();
|
|
|
|
|
|
if (PointList.IsEmpty()) return;
|
|
|
dfPoint dp = PointList.GetHead();
|
|
|
m_controlPoints.AddTail(dp);
|
|
|
}
|
|
|
|
|
|
POSITION CItemCurveSpline::NextCurve(void)
|
|
|
{
|
|
|
AppendPoint();
|
|
|
return CItemCurve::NextCurve();
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::AppendPoint(void)
|
|
|
{
|
|
|
if (!IsSplineState())
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
if (m_controlPoints.GetCount() <= 1)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Build complete spline curve including current mouse position
|
|
|
CPointList finalControlPoints;
|
|
|
POSITION pos = m_controlPoints.GetHeadPosition();
|
|
|
while (pos)
|
|
|
{
|
|
|
finalControlPoints.AddTail(m_controlPoints.GetNext(pos));
|
|
|
}
|
|
|
finalControlPoints.AddTail(m_dpLastMousePos);
|
|
|
|
|
|
// Convert to sampled points and add to finalized curve
|
|
|
CPointList sampledPoints;
|
|
|
BuildSplineCurve(finalControlPoints, sampledPoints);
|
|
|
|
|
|
pos = sampledPoints.GetHeadPosition();
|
|
|
while (pos)
|
|
|
{
|
|
|
dfPoint dp = sampledPoints.GetNext(pos);
|
|
|
AddPoint(dp);
|
|
|
}
|
|
|
|
|
|
clearSplineData();
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::clearSplineData()
|
|
|
{
|
|
|
m_controlPoints.RemoveAll();
|
|
|
m_cachedScreenPoints.clear();
|
|
|
}
|
|
|
|
|
|
BOOL CItemCurveSpline::IsSplineState(void)
|
|
|
{
|
|
|
if (m_AddLineState == CURVE_STATE_SPLINE)
|
|
|
return TRUE;
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
BOOL CItemCurveSpline::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
|
{
|
|
|
switch (nChar)
|
|
|
{
|
|
|
case VK_BACK:
|
|
|
if (IsSplineState() && m_controlPoints.GetCount() > 0)
|
|
|
{
|
|
|
RemoveTail();
|
|
|
return FALSE;
|
|
|
}
|
|
|
break;
|
|
|
case '1': //Line
|
|
|
break;
|
|
|
case '2': //Arc
|
|
|
break;
|
|
|
case '3': //Spline
|
|
|
break;
|
|
|
case '9': //90 degree
|
|
|
break;
|
|
|
}
|
|
|
return CItemCurve::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
|
}
|
|
|
|
|
|
BOOL CItemCurveSpline::IsOnlyPointListTail(void)
|
|
|
{
|
|
|
if (m_controlPoints.GetCount() == 1 && !PointList.IsEmpty())
|
|
|
{
|
|
|
dfPoint ds = m_controlPoints.GetTail();
|
|
|
dfPoint dp = PointList.GetTail();
|
|
|
if (AfxGetPublicFunction()->Distance2(ds.x0, ds.y0, dp.x0, dp.y0) <= DBL_MIN)
|
|
|
{
|
|
|
return TRUE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::OnCancel(void)
|
|
|
{
|
|
|
clearSplineData();
|
|
|
CItemCurve::OnCancel();
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::RemoveTail(void)
|
|
|
{
|
|
|
if (m_controlPoints.GetCount() == 0)
|
|
|
return;
|
|
|
|
|
|
// Normal case: multiple control points, incremental update handles erase+redraw
|
|
|
if (m_controlPoints.GetCount() > 1)
|
|
|
{
|
|
|
m_controlPoints.RemoveTail();
|
|
|
DrawPreview(m_pScreenDC);
|
|
|
DrawControlPointHandles(m_pScreenDC);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Only one control point left: erase preview and fall back to PointList
|
|
|
ErasePreview(m_pScreenDC);
|
|
|
|
|
|
if (PointList.IsEmpty())
|
|
|
{
|
|
|
clearSplineData();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Undo last finalized point
|
|
|
PointList.RemoveTail();
|
|
|
|
|
|
if (PointList.IsEmpty())
|
|
|
{
|
|
|
clearSplineData();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Restart spline from new tail of PointList
|
|
|
m_controlPoints.RemoveAll();
|
|
|
m_controlPoints.AddTail(PointList.GetTail());
|
|
|
DrawPreview(m_pScreenDC);
|
|
|
DrawControlPointHandles(m_pScreenDC);
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::Undo(void)
|
|
|
{
|
|
|
if (m_controlPoints.IsEmpty())
|
|
|
{
|
|
|
CItemCurveArc::Undo();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
RemoveTail();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::Redo(void)
|
|
|
{
|
|
|
if (IsOnlyPointListTail())
|
|
|
{
|
|
|
CItemCurveArc::Redo();
|
|
|
|
|
|
m_controlPoints.RemoveAll();
|
|
|
if (!PointList.IsEmpty())
|
|
|
{
|
|
|
dfPoint dp = PointList.GetTail();
|
|
|
m_controlPoints.AddTail(dp);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
BOOL CItemCurveSpline::IsCanUndo(void)
|
|
|
{
|
|
|
if (IsOnlyPointListTail())
|
|
|
return CItemCurveArc::IsCanUndo();
|
|
|
return !m_controlPoints.IsEmpty();
|
|
|
}
|
|
|
|
|
|
BOOL CItemCurveSpline::IsCanRedo(void)
|
|
|
{
|
|
|
if (IsOnlyPointListTail())
|
|
|
return CItemCurveArc::IsCanRedo();
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::EraseAuxiliarySpline(CDC * pScreenDC)
|
|
|
{
|
|
|
ErasePreview(pScreenDC);
|
|
|
}
|
|
|
|
|
|
void CItemCurveSpline::DrawAssistant(CDC * pScreenDC, int mouseX, int mouseY)
|
|
|
{
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ػ棬<D8BB><E6A3AC><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>ʧЧ<CAA7><D0A7><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD>
|
|
|
m_cachedScreenPoints.clear();
|
|
|
DrawPreview(pScreenDC);
|
|
|
DrawControlPointHandles(pScreenDC);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
//CItemCurveMerge
|
|
|
|
|
|
CItemCurveMerge::CItemCurveMerge(CSigmaDoc * ppDoc)
|
|
|
: CItemCurveSpline(ppDoc)
|
|
|
{
|
|
|
m_pItemSelect = new CItemSelectElement(ppDoc);
|
|
|
m_pItemSelect->EnableDraw(FALSE);
|
|
|
m_pItemSelect->SetCompareIdea(1);
|
|
|
m_pItemSelect->SetNumber(-1);
|
|
|
|
|
|
//CMainFrame* pmf = (CMainFrame*)GetDoc()->GetMainFrame();
|
|
|
//if(pmf)pmf->ShowToolBar(IDR_TOOLBAR_PLINE_INSERT, TRUE);
|
|
|
}
|
|
|
|
|
|
CItemCurveMerge::~CItemCurveMerge(void)
|
|
|
{
|
|
|
if (m_pItemSelect)delete m_pItemSelect;
|
|
|
m_pItemSelect = NULL;
|
|
|
|
|
|
//CMainFrame* pmf = (CMainFrame*)GetDoc()->GetMainFrame();
|
|
|
//if(pmf)pmf->ShowToolBar(IDR_TOOLBAR_PLINE_INSERT, FALSE);
|
|
|
}
|
|
|
|
|
|
BOOL CItemCurveMerge::IsMergeState(void)
|
|
|
{
|
|
|
if (m_AddLineState == CURVE_STATE_MERGE)
|
|
|
return TRUE;
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::OnLButtonDown(CDC *pDC, UINT nFlags, CPoint point, int vk)
|
|
|
{
|
|
|
GetDC()->Create(pDC);
|
|
|
if (IsMergeState())
|
|
|
{
|
|
|
m_pItemSelect->OnLButtonDown(pDC, nFlags, point, vk);
|
|
|
if (m_pItemSelect->GetSelectCount() == 1)
|
|
|
{
|
|
|
EraseScreenLines();
|
|
|
CPoint2D dp = GetDC()->GetReal(point);
|
|
|
POSITION pos = m_pItemSelect->GetSelectItem(0);
|
|
|
MergeElement(pos, dp);
|
|
|
m_pItemSelect->RemoveAllSelect(); //?????????
|
|
|
RedrawScreenLines();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
CItemCurveSpline::OnLButtonDown(pDC, nFlags, point, vk);
|
|
|
}
|
|
|
|
|
|
int CItemCurveMerge::OnMouseMove(CDC *pDC, UINT nFlags, CPoint point)// , BYTE*& destBuffer, int& destLen)
|
|
|
{
|
|
|
if (IsMergeState() || m_AddLineState == CURVE_STATE_LINE || m_AddLineState == CURVE_STATE_ANGLE)
|
|
|
{
|
|
|
CItemCurve::OnMouseMove(pDC, nFlags, point);
|
|
|
return 1;
|
|
|
}
|
|
|
SetScreenDC(pDC);
|
|
|
GetDC()->Create(pDC);
|
|
|
|
|
|
int count = m_ptDisposableList.GetSize() / 2;
|
|
|
for (int i = 0; i < count; i++)
|
|
|
{
|
|
|
dfPoint pt1 = m_ptDisposableList.GetHead();
|
|
|
m_ptDisposableList.RemoveHead();
|
|
|
dfPoint pt2 = m_ptDisposableList.GetHead();
|
|
|
m_ptDisposableList.RemoveHead();
|
|
|
DrawLine(pt1, pt2);
|
|
|
}
|
|
|
m_ptDisposableList.RemoveAll();
|
|
|
CItemCurveSpline::OnMouseMove(pDC, nFlags, point);// , destBuffer, destLen);
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::OnLButtonUp(CDC *pDC, UINT nFlags, CPoint point, int vk)
|
|
|
{
|
|
|
if (IsMergeState())
|
|
|
{
|
|
|
m_pItemSelect->OnLButtonUp(pDC, nFlags, point, vk);
|
|
|
}
|
|
|
else
|
|
|
CItemCurveSpline::OnLButtonUp(pDC, nFlags, point, vk);
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::DrawAssistant(CDC * pScreenDC, int mouseX, int mouseY)
|
|
|
{
|
|
|
if (m_AddLineState == CURVE_STATE_SPLINE)
|
|
|
{
|
|
|
CItemCurveSpline::DrawAssistant(pScreenDC, mouseX, mouseY);
|
|
|
}
|
|
|
CItemCurve::DrawAssistant(pScreenDC, mouseX, mouseY);
|
|
|
}
|
|
|
|
|
|
BOOL CItemCurveMerge::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
|
{
|
|
|
if (IsMergeState())
|
|
|
return m_pItemSelect->OnSetCursor(pWnd, nHitTest, message);
|
|
|
return CItemCurveSpline::OnSetCursor(pWnd, nHitTest, message);
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::EndCurve()
|
|
|
{
|
|
|
if (IsSplineState())
|
|
|
{
|
|
|
CItemCurveSpline::NextCurve();
|
|
|
return;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
CItemCurve::NextCurve();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::AddCurve()
|
|
|
{
|
|
|
NextCurve();
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::AutoClose(void)
|
|
|
{
|
|
|
AppendPoint();
|
|
|
|
|
|
if (PointList.IsEmpty())
|
|
|
return;
|
|
|
|
|
|
dfPoint dp = PointList.GetHead();
|
|
|
m_ptDisposableList.AddTail(dp); //????????
|
|
|
m_ptDisposableList.AddTail(PointList.GetTail());
|
|
|
|
|
|
m_ptDisposableList.AddTail(m_dpLastMousePos); //?????
|
|
|
m_ptDisposableList.AddTail(PointList.GetTail());
|
|
|
|
|
|
AddPoint(dp);
|
|
|
m_dpLastMousePos = dp;
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::ChangeMergeState()
|
|
|
{
|
|
|
if (m_AddLineState == CURVE_STATE_MERGE)
|
|
|
{
|
|
|
CItemCurve::RestoreCurveState();
|
|
|
|
|
|
if (PointList.IsEmpty())
|
|
|
return;
|
|
|
dfPoint dp = PointList.GetTail();
|
|
|
m_controlPoints.AddTail(dp);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (IsSplineState())
|
|
|
{
|
|
|
AppendPoint();
|
|
|
}
|
|
|
CItemCurve::SetCurveState(CURVE_STATE_MERGE, NULL);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::OnCancel(void)
|
|
|
{
|
|
|
switch (m_AddLineState)
|
|
|
{
|
|
|
case CURVE_STATE_MERGE:
|
|
|
case CURVE_STATE_LINE:
|
|
|
case CURVE_STATE_ARC:
|
|
|
case CURVE_STATE_ANGLE:
|
|
|
CItemCurve::OnCancel();
|
|
|
break;
|
|
|
case CURVE_STATE_SPLINE:
|
|
|
CItemCurveSpline::OnCancel();
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::SetCurveState(int state, CDC * pDC)
|
|
|
{
|
|
|
if (state == m_AddLineState)//????????
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
if (state == CURVE_STATE_MERGE)
|
|
|
{
|
|
|
m_AddLineState = CURVE_STATE_MERGE;
|
|
|
CItemCurve::SetCurveState(CURVE_STATE_MERGE, NULL);
|
|
|
return;
|
|
|
}
|
|
|
if (state == CURVE_STATE_DRAWING)
|
|
|
{
|
|
|
// No special handling needed
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
CItemCurveSpline::SetCurveState(state, pDC);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
void CItemCurveMerge::EreaseOldLine()
|
|
|
{
|
|
|
dfPoint ptTail = PointList.GetTail();
|
|
|
CPoint ptT = GetDC()->GetScreen(ptTail);
|
|
|
CPoint ptPrev = GetDC()->GetScreen(m_dpLastMousePos);
|
|
|
DrawLineScreen(ptPrev.x, ptPrev.y, ptT.x, ptT.y);
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::DrawLine(dfPoint pt1, dfPoint pt2)
|
|
|
{
|
|
|
CPoint pt1S = GetDC()->GetScreen(pt1);
|
|
|
CPoint pt2S = GetDC()->GetScreen(pt2);
|
|
|
DrawLineScreen(pt1S.x, pt1S.y, pt2S.x, pt2S.y);
|
|
|
}
|
|
|
|
|
|
void CItemCurveMerge::MergeElement(POSITION pos, CPoint2D& dp)
|
|
|
{
|
|
|
if (pos == NULL) return;
|
|
|
|
|
|
if (m_pDoc == NULL)
|
|
|
return;
|
|
|
|
|
|
COne* pOne = m_pDoc->GetDraw()->GetAt(pos);
|
|
|
if (pOne == NULL)
|
|
|
return;
|
|
|
|
|
|
switch (pOne->GetType())
|
|
|
{
|
|
|
case DOUBLEFOX_CURVE:
|
|
|
{
|
|
|
CCurveEx* pc = (CCurveEx*)pOne->GetValue();
|
|
|
double dis = AfxGetPublicFunction()->Distance2(dp.x0, dp.y0, pc->x[0], pc->y[0]);
|
|
|
if (dis < AfxGetPublicFunction()->Distance2(dp.x0, dp.y0, pc->x[pc->num - 1], pc->y[pc->num - 1]))//????
|
|
|
{
|
|
|
for (int i = 0; i < pc->num; i++)
|
|
|
this->AddPointFromCoordinate(pc->x[i], pc->y[i]);
|
|
|
}
|
|
|
else//????
|
|
|
{
|
|
|
int lastIndex = pc->num - 1;
|
|
|
for (int i = lastIndex; i >= 0; i--)
|
|
|
this->AddPointFromCoordinate(pc->x[i], pc->y[i]);
|
|
|
}
|
|
|
m_dpLastMousePos = PointList.GetTail();
|
|
|
}
|
|
|
break;
|
|
|
case DOUBLEFOX_MXN:
|
|
|
case DOUBLEFOX_XYZ:
|
|
|
case DOUBLEFOX_POINT:
|
|
|
case DOUBLEFOX_TEXT:
|
|
|
case DOUBLEFOX_ELLIPSE:
|
|
|
case DOUBLEFOX_CIRCLE:
|
|
|
case DOUBLEFOX_INSERT:
|
|
|
case DOUBLEFOX_DRAW:
|
|
|
case DOUBLEFOX_DRAW_RECT:
|
|
|
case DOUBLEFOX_PROPORTION:
|
|
|
case DOUBLEFOX_FRAME:
|
|
|
case DOUBLEFOX_IMAGE:
|
|
|
case DOUBLEFOX_OLE:
|
|
|
case DOUBLEFOX_TREE:
|
|
|
case DOUBLEFOX_WMF:
|
|
|
case DOUBLEFOX_STATION:
|
|
|
case DOUBLEFOX_MTEXT:
|
|
|
{
|
|
|
CPointNameBase* pPoint = (CPointNameBase*)pOne->GetValue();
|
|
|
dfPoint dp;
|
|
|
dp.x0 = pPoint->x0;
|
|
|
dp.y0 = pPoint->y0;
|
|
|
AddPoint(dp);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static CRect CalculateHandleRect(LPPOINT pPoint)
|
|
|
{
|
|
|
CRect rc(*pPoint, *pPoint);
|
|
|
//int d = m_HandleSize / 2; //m_HandleSize = 8
|
|
|
int d = 4;
|
|
|
rc.InflateRect(d, d);
|
|
|
return rc;
|
|
|
}
|
|
|
}//namespace
|
|
|
|