|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
//文件: CItem类扩展
|
|
|
//主要功能:
|
|
|
// 操作各类元素或完成一定的功能
|
|
|
//
|
|
|
//程序编写: 2006-12-07
|
|
|
//
|
|
|
//
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "StdAfx.h"
|
|
|
#include ".\itemsolid.h"
|
|
|
#include "SigmaDoc.h"
|
|
|
#include "SigmaView.h"
|
|
|
#include "DrawOperator/CurveClosure.h"
|
|
|
#include "StatusDefine.h"
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
//CItemSolidLink
|
|
|
|
|
|
CItemSolidLink::CItemSolidLink(CSigmaDoc * ppDoc)
|
|
|
: CItemLinkCurve(ppDoc)
|
|
|
{
|
|
|
this->SetType(ITEM_SOLID_LINK);
|
|
|
num = -1;
|
|
|
}
|
|
|
|
|
|
CItemSolidLink::~CItemSolidLink(void)
|
|
|
{
|
|
|
RemoveAllSelect();
|
|
|
}
|
|
|
|
|
|
BOOL CItemSolidLink::DoSelectEnd(void)
|
|
|
{
|
|
|
if (SelectList.GetCount() == 0) return FALSE;
|
|
|
CSigmaDoc * pDoc = GetDoc();
|
|
|
|
|
|
SELECT_ITEM st1, st2;
|
|
|
COne *pOne1, *pOne2;
|
|
|
CCurveEx *p1, *p2;
|
|
|
CList<dfPoint, dfPoint> PointList;
|
|
|
dfPoint dp;
|
|
|
int n;
|
|
|
double dish, dist, dis11, dis12, dis21, dis22;
|
|
|
|
|
|
POSITION pos = SelectList.GetHeadPosition();
|
|
|
|
|
|
st1 = SelectList.GetNext(pos);
|
|
|
pOne1 = pDoc->GetDraw()->GetAt(st1.pos);
|
|
|
p1 = (CCurveEx*)pOne1->GetValue();
|
|
|
p1->GetPoint(PointList, FALSE);
|
|
|
|
|
|
while (pos)
|
|
|
{
|
|
|
st2 = SelectList.GetNext(pos);
|
|
|
pOne2 = pDoc->GetDraw()->GetAt(st2.pos);
|
|
|
p2 = (CCurveEx*)pOne2->GetValue();
|
|
|
|
|
|
n = p2->num - 1;
|
|
|
dp = PointList.GetHead();
|
|
|
dis11 = ::AfxGetPublicFunction()->Distance2(dp.x0, dp.y0, p2->x[0], p2->y[0]);
|
|
|
dis12 = ::AfxGetPublicFunction()->Distance2(dp.x0, dp.y0, p2->x[n], p2->y[n]);
|
|
|
dish = min(dis11, dis12);
|
|
|
|
|
|
dp = PointList.GetTail();
|
|
|
dis21 = ::AfxGetPublicFunction()->Distance2(dp.x0, dp.y0, p2->x[0], p2->y[0]);
|
|
|
dis22 = ::AfxGetPublicFunction()->Distance2(dp.x0, dp.y0, p2->x[n], p2->y[n]);
|
|
|
dist = min(dis21, dis22);
|
|
|
|
|
|
if (dish < dist)
|
|
|
{
|
|
|
if (dis11 < dis12) p2->GetPoint(PointList, FALSE, TRUE);
|
|
|
else p2->GetPoint(PointList, TRUE, TRUE);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (dis21 < dis22) p2->GetPoint(PointList, FALSE, FALSE);
|
|
|
else p2->GetPoint(PointList, TRUE, FALSE);
|
|
|
}
|
|
|
}
|
|
|
dp = PointList.GetHead();
|
|
|
PointList.AddTail(dp);
|
|
|
|
|
|
CCurveEx *pCurve = new CCurveEx;
|
|
|
pCurve->SetPoints(PointList, 2);
|
|
|
pCurve->m_type = PLINE_SOLID;
|
|
|
pos = AddElement(pCurve, DOUBLEFOX_CURVE, true, true);
|
|
|
PointList.RemoveAll();
|
|
|
|
|
|
COne* pOne = GetDoc()->GetDraw()->GetAt(pos);
|
|
|
GetView()->ActionAdd(pOne, ID_EDIT_SOLID_LINK_RANGE);
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
int CItemSolidLink::GetSubMenu()
|
|
|
{
|
|
|
return 5;
|
|
|
}
|
|
|
|
|
|
void CItemSolidLink::ClearAssistantCurve(void)
|
|
|
{
|
|
|
//删除辅助曲线
|
|
|
if (AssistantCurveList.IsEmpty()) return;
|
|
|
/*if(::AfxMessageBox(IDS_STRING_DELETE_ASSISTANT,MB_YESNO|MB_ICONQUESTION)!=IDYES)
|
|
|
return;*/
|
|
|
SELECT_ITEM item;
|
|
|
POSITION p, pt;
|
|
|
POSITION pos = SelectList.GetHeadPosition();
|
|
|
while (pos)
|
|
|
{
|
|
|
pt = pos;
|
|
|
item = SelectList.GetNext(pos);
|
|
|
p = AssistantCurveList.Find(item.pos);
|
|
|
if (p) SelectList.RemoveAt(pt);
|
|
|
}
|
|
|
GetDoc()->InvalidateDelete(AssistantCurveList);
|
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
//CItemSolid
|
|
|
|
|
|
CItemSolid::CItemSolid(CSigmaDoc * ppDoc)
|
|
|
: CItemSolidLink(ppDoc)
|
|
|
{
|
|
|
this->SetType(ITEM_SOLID);
|
|
|
m_nCompareIdea = 0;
|
|
|
num = -1;
|
|
|
m_iMaxExtendLength = 5000;
|
|
|
}
|
|
|
|
|
|
CItemSolid::~CItemSolid(void)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
int CItemSolid::GetSubMenu()
|
|
|
{
|
|
|
return 5;
|
|
|
}
|
|
|
|
|
|
int CItemSolid::OnMouseMove(CDC* pDC, UINT nFlags, CPoint point)
|
|
|
{
|
|
|
return CItemLinkCurve::OnMouseMove(pDC, nFlags, point);
|
|
|
//CSigmaDoc * pDoc = GetDoc();
|
|
|
//CString info;
|
|
|
//info.Format(IDS_STRING_CONFIRM_NEXT_CURVE,(int)SelectList.GetCount()+1);
|
|
|
//pDoc->SetStatusBarInfo(0,info);
|
|
|
}
|
|
|
|
|
|
CCrossPoint CItemSolid::GetPoint(SELECT_ITEM& item, CCurveEx* p1, CCurveEx* p2, CCrossPoint& otherPoint)
|
|
|
{
|
|
|
CCrossPoint CurPoint;
|
|
|
//直接连接第一条线与最后一条线形成填充区域,需要判断选择哪端
|
|
|
if (::AfxGetPublicFunction()->Distance2(item.point.x0, item.point.y0, p1->x[0], p1->y[0]) >
|
|
|
::AfxGetPublicFunction()->Distance2(item.point.x0, item.point.y0, p1->x[p1->num - 1], p1->y[p1->num - 1]))
|
|
|
{
|
|
|
CurPoint.x[0] = p1->l[p1->num - 1]; //tail point
|
|
|
otherPoint.x[0] = p1->l[0]; //head point
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
CurPoint.x[0] = p1->l[0]; //head point
|
|
|
otherPoint.x[0] = p1->l[p1->num - 1]; //tail point
|
|
|
}
|
|
|
|
|
|
if (::AfxGetPublicFunction()->Distance2(item.point.x0, item.point.y0, p2->x[0], p2->y[0]) >
|
|
|
::AfxGetPublicFunction()->Distance2(item.point.x0, item.point.y0, p2->x[p2->num - 1], p1->y[p2->num - 1]))
|
|
|
{
|
|
|
CurPoint.x[1] = p2->l[p2->num - 1]; //tail point
|
|
|
otherPoint.x[1] = p2->l[0]; //head point
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
CurPoint.x[1] = p2->l[0]; //head point
|
|
|
otherPoint.x[1] = p2->l[p2->num - 1]; //tail point
|
|
|
}
|
|
|
CurPoint.curve = p1;
|
|
|
otherPoint.curve = p1;
|
|
|
return CurPoint;
|
|
|
}
|
|
|
|
|
|
BOOL CItemSolid::CreateTwoCurveSolid(SELECT_ITEM& item1, SELECT_ITEM& item2)
|
|
|
{
|
|
|
|
|
|
BOOL ret = true;
|
|
|
CSigmaDoc * pDoc = GetDoc();
|
|
|
CCurveEx* p1 = (CCurveEx*)pDoc->GetDraw()->GetAtValue(item1.pos);
|
|
|
CCurveEx* p2 = (CCurveEx*)pDoc->GetDraw()->GetAtValue(item2.pos);
|
|
|
|
|
|
CCrossPoint cp;
|
|
|
CCrossList cl;
|
|
|
p1->Cross(*p2, cl);
|
|
|
if (cl.GetCount() >= 1)
|
|
|
{
|
|
|
cp = cl.GetHead();
|
|
|
}
|
|
|
CList <dfPoint, dfPoint> pointList;
|
|
|
CURVE_SEGMENT segment1;
|
|
|
|
|
|
segment1.pCurve = p1;
|
|
|
//选择第一条曲线离选择点近的端点
|
|
|
double ds = ::AfxGetPublicFunction()->Distance2(item1.point.x0, item1.point.y0, p1->x[0], p1->y[0]);
|
|
|
double de = ::AfxGetPublicFunction()->Distance2(item1.point.x0, item1.point.y0, p1->x[p1->num - 1], p1->y[p1->num - 1]);
|
|
|
if (ds < de)
|
|
|
{
|
|
|
segment1.head = p1->l[0];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
segment1.head = p1->l[p1->num - 1];
|
|
|
}
|
|
|
segment1.tail = cp.x[0];
|
|
|
GetCurve(segment1, pointList);
|
|
|
|
|
|
CURVE_SEGMENT segment2;
|
|
|
segment2.pCurve = p2;
|
|
|
//选择第二条曲线离选择点近的端点
|
|
|
ds = ::AfxGetPublicFunction()->Distance2(item2.point.x0, item2.point.y0, p2->x[0], p2->y[0]);
|
|
|
de = ::AfxGetPublicFunction()->Distance2(item2.point.x0, item2.point.y0, p2->x[p2->num - 1], p2->y[p2->num - 1]);
|
|
|
segment2.head = cp.x[1];
|
|
|
if (ds < de)
|
|
|
{
|
|
|
segment2.tail = p2->l[0];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
segment2.tail = p2->l[p2->num - 1];
|
|
|
}
|
|
|
GetCurve(segment2, pointList);
|
|
|
|
|
|
if (pointList.GetCount() < 2) return NULL;
|
|
|
CCurveEx* pCurve = new CCurveEx;
|
|
|
pCurve->SetPoints(pointList, 2);
|
|
|
pCurve->m_type = PLINE_SOLID;
|
|
|
|
|
|
POSITION pos = this->AddElement(pCurve, DOUBLEFOX_CURVE, true, true);
|
|
|
pDoc->Invalidate(pos);
|
|
|
SelectList.RemoveAll();
|
|
|
|
|
|
COne* pOne = pDoc->GetDraw()->GetAt(pos);
|
|
|
GetView()->ActionAdd(pOne, ID_EDIT_GETSOLIDRANGE);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
BOOL CItemSolid::DoSelectEnd(void)
|
|
|
{
|
|
|
if (SelectList.GetCount() == 0) //没有选择曲线
|
|
|
return TRUE;
|
|
|
CSigmaDoc * pDoc = GetDoc();
|
|
|
|
|
|
POSITION pos;
|
|
|
SELECT_ITEM item;
|
|
|
item = SelectList.GetTail();
|
|
|
CCurveEx* p1 = (CCurveEx*)pDoc->GetDraw()->GetAtValue(item.pos);
|
|
|
|
|
|
if (SelectList.GetCount() == 1) //当为一条曲线时,直接进行充填
|
|
|
{
|
|
|
CCurveEx* pCurve = new CCurveEx;
|
|
|
*pCurve = *p1;
|
|
|
pCurve->m_type = PLINE_SOLID;
|
|
|
pos = this->AddElement(pCurve, DOUBLEFOX_CURVE, true, false);
|
|
|
pDoc->Invalidate(pos);
|
|
|
SelectList.RemoveAll();
|
|
|
|
|
|
//for undo/redo
|
|
|
COne* pOne = pDoc->GetDraw()->GetAt(pos);
|
|
|
GetView()->ActionAdd(pOne, ID_EDIT_GETSOLIDRANGE);
|
|
|
|
|
|
return TRUE;
|
|
|
}
|
|
|
BOOL bEnd = FALSE;
|
|
|
|
|
|
|
|
|
//计算第一条线与最后一条线的交点
|
|
|
item = SelectList.GetHead();
|
|
|
CCurveEx* p2 = (CCurveEx*)pDoc->GetDraw()->GetAtValue(item.pos);
|
|
|
|
|
|
CCrossPoint CurPoint;
|
|
|
CCrossPoint otherPoint;
|
|
|
CCrossList crossList;
|
|
|
int et = CrossWithExtend(p1, p2, crossList);
|
|
|
if (crossList.GetCount() == 0)
|
|
|
{
|
|
|
////该曲线与第一条曲线无交点,是否重新选择曲线,或立即绘制一条辅助曲线?选择“否”将直接连接曲线结束充填。
|
|
|
//AfxMessageBox(IDS_STRING_SOLID_NOCROSS1);
|
|
|
//return FALSE;
|
|
|
|
|
|
/*if(::AfxMessageBox(IDS_STRING_SOLID_NOCROSS1, MB_YESNO|MB_ICONQUESTION) == IDYES)
|
|
|
return FALSE;*/
|
|
|
CurPoint = GetPoint(item, p1, p2, otherPoint);
|
|
|
bEnd = TRUE;
|
|
|
}
|
|
|
if (SelectList.GetCount() == 2)//仅有两条曲线时
|
|
|
{
|
|
|
if (crossList.GetCount() == 1)//两条曲线一个交点
|
|
|
{
|
|
|
//crossList.RemoveAll();
|
|
|
//et = CrossWithMustExtend(p1, p2, crossList);
|
|
|
/*if (crossList.GetCount() < 2)
|
|
|
{*/
|
|
|
//直接创建闭合区域,按就近原则选择曲线端点和交点共同构成闭合区域
|
|
|
CreateTwoCurveSolid(SelectList.GetHead(), SelectList.GetTail());
|
|
|
bEnd = TRUE;
|
|
|
return TRUE;
|
|
|
/*}*/
|
|
|
}
|
|
|
if (!bEnd)//两条曲线多个交点
|
|
|
{
|
|
|
CurPoint = crossList.GetHead();
|
|
|
PrevPoint = crossList.GetTail();
|
|
|
::AfxGetPublicFunction()->Swap(PrevPoint.x[0], PrevPoint.x[1]); //为了适应下面的代码,需要交换位置
|
|
|
}
|
|
|
FirstPoint = PrevPoint;
|
|
|
}
|
|
|
else if (!bEnd)
|
|
|
CurPoint = GetNearestCrossPoint(crossList, item.point);
|
|
|
|
|
|
CURVE_SEGMENT segment;
|
|
|
segment.head = PrevPoint.x[1];
|
|
|
segment.tail = CurPoint.x[0];
|
|
|
segment.pCurve = p1;
|
|
|
if (et == 1 || et == 3 || m_bExtendLastCurve) segment.m_bExtend = TRUE;
|
|
|
else segment.m_bExtend = FALSE;
|
|
|
CurveGroup.AddTail(segment);
|
|
|
|
|
|
segment.head = CurPoint.x[1];
|
|
|
segment.tail = FirstPoint.x[0];
|
|
|
segment.pCurve = p2;
|
|
|
if (et == 2 || et == 3 || m_bExtendFirstCurve) segment.m_bExtend = TRUE;
|
|
|
else segment.m_bExtend = FALSE;
|
|
|
CurveGroup.AddHead(segment);
|
|
|
|
|
|
if (CreateCurve(CurveGroup) == NULL)
|
|
|
{
|
|
|
CurveGroup.RemoveTail();
|
|
|
segment.head = PrevPoint.x[1];
|
|
|
segment.tail = otherPoint.x[0];
|
|
|
segment.pCurve = p1;
|
|
|
if (et == 1 || et == 3 || m_bExtendLastCurve) segment.m_bExtend = TRUE;
|
|
|
else segment.m_bExtend = FALSE;
|
|
|
CurveGroup.AddTail(segment);
|
|
|
|
|
|
CreateCurve(CurveGroup);
|
|
|
}
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
POSITION CItemSolid::CreateCurve(CList<CURVE_SEGMENT, CURVE_SEGMENT>& cg)
|
|
|
{
|
|
|
CList <dfPoint, dfPoint> PointList;
|
|
|
CURVE_SEGMENT segment;
|
|
|
POSITION pos = cg.GetHeadPosition();
|
|
|
while (pos)
|
|
|
{
|
|
|
segment = cg.GetNext(pos);
|
|
|
GetCurve(segment, PointList);
|
|
|
}
|
|
|
|
|
|
if (PointList.GetCount() < 2) return NULL;
|
|
|
|
|
|
CCurveEx* pCurve = new CCurveEx;
|
|
|
pCurve->SetPoints(PointList, 2);
|
|
|
pCurve->m_type = PLINE_SOLID;
|
|
|
|
|
|
//计算形成的区域是否是首尾曲线与曲线本身相交
|
|
|
PointList.RemoveHead();
|
|
|
PointList.RemoveHead();
|
|
|
PointList.RemoveTail();
|
|
|
PointList.RemoveTail();
|
|
|
CCurveEx* pe = new CCurveEx;
|
|
|
pe->SetPoints(PointList, 2);
|
|
|
CCurveEx *pc = new CCurveEx;
|
|
|
pc->Create(2);
|
|
|
pc->x[0] = pCurve->x[0]; pc->y[0] = pCurve->y[0];
|
|
|
pc->x[1] = pCurve->x[pCurve->num - 1]; pc->y[1] = pCurve->y[pCurve->num - 1];
|
|
|
pc->GetLocation();
|
|
|
|
|
|
CCrossList cross;
|
|
|
pe->Cross(*(CCurve*)pc, cross);
|
|
|
if (cross.GetCount() > 0)
|
|
|
{
|
|
|
delete pCurve;
|
|
|
delete pc;
|
|
|
delete pe;
|
|
|
return NULL;
|
|
|
}
|
|
|
delete pc;
|
|
|
delete pe;
|
|
|
|
|
|
CSigmaDoc * pDoc = GetDoc();
|
|
|
pos = this->AddElement(pCurve, DOUBLEFOX_CURVE, true, true);
|
|
|
pDoc->Invalidate(pos);
|
|
|
SelectList.RemoveAll();
|
|
|
|
|
|
COne* pOne = pDoc->GetDraw()->GetAt(pos);
|
|
|
GetView()->ActionAdd(pOne, ID_EDIT_GETSOLIDRANGE);
|
|
|
|
|
|
/*CList<POSITION,POSITION> select;
|
|
|
pos=SelectList.GetHeadPosition();
|
|
|
while(pos) select.AddTail(SelectList.GetNext(pos).pos);
|
|
|
pDoc->InvalidateSelection(select);*/
|
|
|
|
|
|
return pos;
|
|
|
}
|
|
|
|
|
|
BOOL CItemSolid::SelectItem(POSITION pos, CPoint2D point)
|
|
|
{
|
|
|
if (pos == NULL) return FALSE;
|
|
|
int cnt = (int)SelectList.GetCount();
|
|
|
CSigmaDoc * pDoc = GetDoc();
|
|
|
|
|
|
//CString info;
|
|
|
//info.Format(IDS_STRING_CONFIRM_NEXT_CURVE,cnt+1);
|
|
|
//pDoc->SetStatusBarInfo(0,info);
|
|
|
if (cnt == 0) return TRUE;
|
|
|
|
|
|
SELECT_ITEM item = SelectList.GetTail();
|
|
|
CCurveEx* p1 = (CCurveEx*)pDoc->GetDraw()->GetAtValue(item.pos);
|
|
|
CCurveEx* p2 = (CCurveEx*)pDoc->GetDraw()->GetAtValue(pos);
|
|
|
|
|
|
CCrossList cross;
|
|
|
pDoc->SetStatusOfCrossPoint(1);
|
|
|
int et = CrossWithExtend(p1, p2, cross);
|
|
|
if (cross.GetCount() == 0)
|
|
|
{
|
|
|
pDoc->SetStatusOfCrossPoint(0);
|
|
|
//该曲线与上条曲线无交点,请从新选择曲线,或立即绘制一条辅助曲线
|
|
|
//AfxMessageBox(IDS_STRING_SOLID_NOCROSS);
|
|
|
int result = MessageBox(GetDrawView()->GetHWND(), "该曲线与上条曲线无交点,请重新选择曲线。", "", MB_OK);
|
|
|
return FALSE;
|
|
|
}
|
|
|
if (cnt == 1)
|
|
|
{
|
|
|
PrevPoint = GetNearestCrossPoint(cross, point);
|
|
|
FirstPoint = PrevPoint;
|
|
|
if (et == 1 || et == 3) m_bExtendFirstCurve = TRUE;
|
|
|
else m_bExtendFirstCurve = FALSE;
|
|
|
if (et == 2 || et == 3) m_bExtendLastCurve = TRUE;
|
|
|
else m_bExtendLastCurve = FALSE;
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
CCrossPoint CurPoint = GetNearestCrossPoint(cross, point);
|
|
|
CURVE_SEGMENT segment;
|
|
|
segment.PrevPoint = PrevPoint; //为UNDO,REDO做备份
|
|
|
segment.m_bExtendLastCurve = m_bExtendLastCurve;
|
|
|
segment.head = PrevPoint.x[1];
|
|
|
segment.tail = CurPoint.x[0];
|
|
|
segment.pCurve = p1;
|
|
|
if (et == 1 || et == 3 || m_bExtendLastCurve) segment.m_bExtend = TRUE;
|
|
|
else segment.m_bExtend = FALSE;
|
|
|
if (et == 2 || et == 3) m_bExtendLastCurve = TRUE;
|
|
|
else m_bExtendLastCurve = FALSE;
|
|
|
|
|
|
CList <dfPoint, dfPoint> PointList;
|
|
|
GetCurve(segment, PointList);
|
|
|
if (PointList.GetCount() == 0)
|
|
|
{
|
|
|
pDoc->SetStatusOfCrossPoint(false);
|
|
|
/*::AfxMessageBox("Error: Null Curve");*/
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
CurveGroup.AddTail(segment);
|
|
|
PrevPoint = CurPoint;
|
|
|
|
|
|
//仅为了显示曲线
|
|
|
CCurveEx* pCurve = new CCurveEx;
|
|
|
pCurve->SetPoints(PointList, 2);
|
|
|
this->Draw(GetDC(), pCurve, RGB(0, 255, 0));
|
|
|
delete pCurve;
|
|
|
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
void _SolidSetCurve(CCrossList& crossList, CCurveEx* pCurve, int countJump)
|
|
|
{
|
|
|
POSITION pos = crossList.GetHeadPosition();
|
|
|
if (countJump > 0) pos = crossList.FindIndex(countJump);
|
|
|
CCrossPoint cp;
|
|
|
while (pos)
|
|
|
{
|
|
|
cp = crossList.GetAt(pos);
|
|
|
cp.curve = pCurve;
|
|
|
crossList.SetAt(pos, cp);
|
|
|
crossList.GetNext(pos);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int NItem::CItemSolid::CrossWithExtend(CCurveEx* p1, CCurveEx* p2, CCrossList& cross)
|
|
|
{
|
|
|
int count = (int)cross.GetCount();
|
|
|
p1->Cross(*(CCurve*)p2, cross);
|
|
|
if (cross.GetCount() > count) return 0;
|
|
|
|
|
|
CCurveEx* pc = new CCurveEx;
|
|
|
*pc = *p2;
|
|
|
pc->Extend(m_iMaxExtendLength, 0); //延伸头
|
|
|
pc->Extend(m_iMaxExtendLength, 1); //延伸尾
|
|
|
p1->Cross(*(CCurve*)pc, cross);
|
|
|
if (cross.GetCount() > count)
|
|
|
{
|
|
|
delete pc;
|
|
|
_SolidSetCurve(cross, p2, count);
|
|
|
return 2;
|
|
|
}
|
|
|
|
|
|
*pc = *p1;
|
|
|
pc->Extend(m_iMaxExtendLength, 0); //延伸头
|
|
|
pc->Extend(m_iMaxExtendLength, 1); //延伸尾
|
|
|
pc->Cross(*(CCurve*)p2, cross);
|
|
|
if (cross.GetCount() > count)
|
|
|
{
|
|
|
delete pc;
|
|
|
_SolidSetCurve(cross, p2, count);
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
CCurveEx* pb = new CCurveEx;
|
|
|
*pb = *p2;
|
|
|
pb->Extend(m_iMaxExtendLength, 0); //延伸头
|
|
|
pb->Extend(m_iMaxExtendLength, 1); //延伸尾
|
|
|
pc->Cross(*(CCurve*)pb, cross);
|
|
|
delete pb;
|
|
|
delete pc;
|
|
|
if (cross.GetCount() > count)
|
|
|
{
|
|
|
_SolidSetCurve(cross, p2, count);
|
|
|
return 3;
|
|
|
}
|
|
|
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
int CItemSolid::CrossWithMustExtend(CCurveEx* p1, CCurveEx* p2, CCrossList& cross)
|
|
|
{
|
|
|
int count = (int)cross.GetCount();
|
|
|
|
|
|
CCurveEx* pc = new CCurveEx;
|
|
|
*pc = *p1;
|
|
|
pc->Extend(m_iMaxExtendLength, 0); //延伸头
|
|
|
pc->Extend(m_iMaxExtendLength, 1); //延伸尾
|
|
|
|
|
|
CCurveEx* pb = new CCurveEx;
|
|
|
*pb = *p2;
|
|
|
pb->Extend(m_iMaxExtendLength, 0); //延伸头
|
|
|
pb->Extend(m_iMaxExtendLength, 1); //延伸尾
|
|
|
|
|
|
pc->Cross(*(CCurve*)pb, cross);
|
|
|
delete pb;
|
|
|
delete pc;
|
|
|
if (cross.GetCount() > count)
|
|
|
{
|
|
|
_SolidSetCurve(cross, p2, count);
|
|
|
return 3;
|
|
|
}
|
|
|
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
void CItemSolid::GetCurve(NItem::CItemSolid::CURVE_SEGMENT& segment, CList <dfPoint, dfPoint>& list)
|
|
|
{
|
|
|
CCurveEx* pc = segment.pCurve;
|
|
|
if (segment.m_bExtend)
|
|
|
{
|
|
|
pc = new CCurveEx;
|
|
|
*pc = *segment.pCurve;
|
|
|
pc->Extend(m_iMaxExtendLength, 0); //延伸头
|
|
|
pc->Extend(m_iMaxExtendLength, 1); //延伸尾
|
|
|
}
|
|
|
pc->GetCurve(segment.head, segment.tail, list);
|
|
|
if (segment.m_bExtend)
|
|
|
delete pc;
|
|
|
}
|
|
|
|
|
|
CCrossPoint CItemSolid::GetNearestCrossPoint(CCrossList& cross, CPoint2D point)
|
|
|
{
|
|
|
ASSERT(cross.GetCount() > 0);
|
|
|
if (cross.GetCount() == 1)
|
|
|
return cross.GetHead();
|
|
|
|
|
|
double dmin = 1e300, dis;
|
|
|
CCrossPoint pt, rpt;
|
|
|
dfPoint dp;
|
|
|
CCurveEx* pCurve;
|
|
|
POSITION pos = cross.GetHeadPosition();
|
|
|
while (pos)
|
|
|
{
|
|
|
pt = cross.GetNext(pos);
|
|
|
pCurve = (CCurveEx*)pt.curve;
|
|
|
dp.l = pt.x[1];
|
|
|
pCurve->GetCoordinate(dp.l, dp.x0, dp.y0, dp.z0);
|
|
|
dis = ::AfxGetPublicFunction()->Distance(point.x0, point.y0, dp.x0, dp.y0);
|
|
|
if (dmin > dis)
|
|
|
{
|
|
|
dmin = dis;
|
|
|
rpt = pt;
|
|
|
}
|
|
|
}
|
|
|
return rpt;
|
|
|
}
|
|
|
|
|
|
void CItemSolid::Undo(void)
|
|
|
{
|
|
|
CItemLinkCurve::Undo();
|
|
|
|
|
|
if (!CurveGroup.IsEmpty())
|
|
|
{
|
|
|
CURVE_SEGMENT cs = CurveGroup.RemoveTail();
|
|
|
PrevPoint = cs.PrevPoint;
|
|
|
m_bExtendLastCurve = cs.m_bExtendLastCurve;
|
|
|
}
|
|
|
|
|
|
if (SelectList.GetCount() == 0) return;
|
|
|
SELECT_ITEM item = SelectList.GetTail();
|
|
|
CSigmaDoc * pDoc = GetDoc();
|
|
|
pDoc->Invalidate(item.pos);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
CItemPathFill::CItemPathFill(CSigmaDoc * ppDoc)
|
|
|
: CItem(ppDoc)
|
|
|
{
|
|
|
this->SetType(ITEM_PATH_FILL);
|
|
|
m_fillMode = 0;
|
|
|
}
|
|
|
|
|
|
CItemPathFill::~CItemPathFill(void)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
//CItemSolidAuto
|
|
|
|
|
|
CItemSolidAuto::CItemSolidAuto(CSigmaDoc * ppDoc)
|
|
|
: CItem(ppDoc)
|
|
|
{
|
|
|
SetType(ITEM_SOLID_AUTO);
|
|
|
m_iMaxExtendLength = 0;
|
|
|
}
|
|
|
|
|
|
CItemSolidAuto::~CItemSolidAuto()
|
|
|
{
|
|
|
ClearCurveList();
|
|
|
}
|
|
|
|
|
|
void CItemSolidAuto::ClearCurveList()
|
|
|
{
|
|
|
CCurveEx* cx;
|
|
|
POSITION p = CurveList.GetHeadPosition();
|
|
|
while (p)
|
|
|
{
|
|
|
cx = (CCurveEx *)(CurveList.GetNext(p));
|
|
|
delete cx;
|
|
|
}
|
|
|
InsideCurveList.RemoveAll();
|
|
|
CurveList.RemoveAll();
|
|
|
}
|
|
|
|
|
|
//得到当前层所有曲线
|
|
|
void NItem::CItemSolidAuto::GetCurves()
|
|
|
{
|
|
|
CurveList.RemoveAll();
|
|
|
InsideCurveList.RemoveAll();
|
|
|
CPositionList plist;
|
|
|
CXy *xy;
|
|
|
xy = GetDoc()->GetDraw();
|
|
|
CRect rect = GetDrawView()->GetClientRect();
|
|
|
CRect8 range;
|
|
|
dfPoint dfpTopleft = GetReal(rect.TopLeft());
|
|
|
dfPoint dfpBottomRight = GetReal(rect.BottomRight());
|
|
|
range.top = dfpTopleft.y0;
|
|
|
range.bottom = dfpBottomRight.y0;
|
|
|
range.left = dfpTopleft.x0;
|
|
|
range.right = dfpBottomRight.x0;
|
|
|
//仅选择当前视图所见的曲线
|
|
|
xy->IsInRange(range, plist, DOUBLEFOX_CURVE, true);
|
|
|
//xy->GetElement(DOUBLEFOX_CURVE, plist, FALSE);
|
|
|
COne *pOne;
|
|
|
CCurveEx* cx;
|
|
|
CCurveEx* pNewCurve;
|
|
|
|
|
|
POSITION pt;
|
|
|
POSITION pos = plist.GetHeadPosition();
|
|
|
while (pos)
|
|
|
{
|
|
|
pt = plist.GetNext(pos);
|
|
|
pOne = (COne *)xy->GetAt(pt);
|
|
|
cx = (CCurveEx*)pOne->value;
|
|
|
|
|
|
pNewCurve = new CCurveEx;
|
|
|
*pNewCurve = *cx;
|
|
|
pNewCurve->GetLocation();
|
|
|
// 一个点的曲线删除
|
|
|
if (pNewCurve->num <= 1)
|
|
|
{
|
|
|
delete pNewCurve;
|
|
|
continue;
|
|
|
}
|
|
|
if (pNewCurve->IsInside(dfp.x0, dfp.y0))
|
|
|
{
|
|
|
InsideCurveList.AddTail(pNewCurve);
|
|
|
}
|
|
|
CurveList.AddTail(pNewCurve);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CItemSolidAuto::OnLButtonDown(CDC *pDC, UINT nFlags, CPoint point, int vk)
|
|
|
{
|
|
|
ClearStatus();
|
|
|
ClearCurveList();
|
|
|
CPoint2D rp = GetDC()->GetReal(point);
|
|
|
|
|
|
dfp.x0 = rp.x0;
|
|
|
dfp.y0 = rp.y0;
|
|
|
//获取视口上的所有曲线
|
|
|
GetCurves();
|
|
|
if (CurveList.IsEmpty())//如果curvelist中无曲线,则提示并退出该状态
|
|
|
{
|
|
|
SetStatusCode(STATUS_CODE_SOLID_NO_CURVE);
|
|
|
SetStatusText(STATUS_TEXT_SOLID_NO_CURVE);
|
|
|
return;
|
|
|
}
|
|
|
//计算图件中包含的曲线相交或闭合的曲线包含的点的最小面积
|
|
|
CCurveEx* pc = CreateSolid();
|
|
|
if (pc)
|
|
|
{
|
|
|
POSITION pos = CurveList.Find(pc);
|
|
|
if (pos)
|
|
|
{
|
|
|
CurveList.RemoveAt(pos);
|
|
|
}
|
|
|
pc->m_type = PLINE_SOLID;
|
|
|
pos = AddElement(pc, DOUBLEFOX_CURVE, true, true);
|
|
|
GetDoc()->Invalidate(pos);
|
|
|
COne* pOne = GetDoc()->GetDraw()->GetAt(pos);
|
|
|
GetView()->ActionAdd(pOne, ID_EDIT_AUTOSOLID);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
SetStatusCode(STATUS_CODE_SOLID_CURVE_NOTCLOSED);
|
|
|
SetStatusText(STATUS_TEXT_SOLID_CURVE_NOTCLOSED);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
CCurveEx* NItem::CItemSolidAuto::CreateSolid()
|
|
|
{
|
|
|
if (CurveList.IsEmpty()) return 0;
|
|
|
CCurveClosure closure(&CurveList);
|
|
|
//创建闭合曲线已包含闭合曲线进行运算
|
|
|
CCurveEx *pCur = closure.CreateClosedCurve(dfp);
|
|
|
CCurveEx *pMinAreaCur = NULL;
|
|
|
if (pCur == NULL || !pCur->IsClosed())
|
|
|
{
|
|
|
if (pCur) delete pCur;
|
|
|
pMinAreaCur = GetMinInsideCurve();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pMinAreaCur = GetMinInsideCurve();
|
|
|
if (pMinAreaCur)
|
|
|
{
|
|
|
if (pCur->Area() < pMinAreaCur->Area()) {
|
|
|
pMinAreaCur = pCur;
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
return pCur;
|
|
|
}
|
|
|
}
|
|
|
return pMinAreaCur;
|
|
|
}
|
|
|
|
|
|
CCurveEx* NItem::CItemSolidAuto::GetMinInsideCurve()
|
|
|
{
|
|
|
CCurveEx *pCurve = NULL;
|
|
|
CCurveEx *pMinAreaCurve = NULL;
|
|
|
POSITION pos;
|
|
|
double minArea = DBL_MAX;
|
|
|
//选取面职最小的闭合区域
|
|
|
pos = InsideCurveList.GetHeadPosition();
|
|
|
while (pos)
|
|
|
{
|
|
|
pCurve = (CCurveEx*)InsideCurveList.GetNext(pos);
|
|
|
if (pCurve)
|
|
|
{
|
|
|
if (pCurve->Area() < minArea)
|
|
|
{
|
|
|
//创建新的曲线
|
|
|
pMinAreaCurve = pCurve;
|
|
|
minArea = pCurve->Area();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return pMinAreaCurve;
|
|
|
}
|
|
|
|
|
|
BOOL CItemSolidAuto::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
|
{
|
|
|
//GetDoc()->GetCursor().SetCursor(CursorCrosshair);
|
|
|
//return GetDoc()->GetCursor().SetCursor();
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
int CItemSolidAuto::GetSubMenu()
|
|
|
{
|
|
|
return 5;
|
|
|
}
|
|
|
|
|
|
// 计算两个向量的叉积
|
|
|
double CItemSolidAuto::CrossProduct(dfPoint p, dfPoint q) {
|
|
|
return p.x0 * q.y0 - p.y0 * q.x0;
|
|
|
}
|
|
|
|
|
|
// 判断两线段是否相交,并求得交点
|
|
|
bool CItemSolidAuto::Cross(dfPoint p1, dfPoint q1, dfPoint p2, dfPoint q2, dfPoint& cr) {
|
|
|
// 计算向量
|
|
|
dfPoint v1;
|
|
|
v1.x0 = q1.x0 - p1.x0;
|
|
|
v1.y0 = q1.y0 - p1.y0;
|
|
|
dfPoint v2;
|
|
|
v2.x0 = q2.x0 - p2.x0;
|
|
|
v2.y0 = q2.y0 - p2.y0;
|
|
|
|
|
|
// 计算叉积
|
|
|
dfPoint p;
|
|
|
p.x0 = p1.x0 - p2.x0;
|
|
|
p.y0 = p1.y0 - p2.y0;
|
|
|
double cp1 = CrossProduct(v2, p);
|
|
|
p.x0 = q1.x0 - p2.x0;
|
|
|
p.y0 = q1.y0 - p2.y0;
|
|
|
double cp2 = CrossProduct(v2, p);
|
|
|
p.x0 = p2.x0 - p1.x0;
|
|
|
p.y0 = p2.y0 - p1.y0;
|
|
|
double cp3 = CrossProduct(v1, p);
|
|
|
p.x0 = q2.x0 - p1.x0;
|
|
|
p.y0 = q2.y0 - p1.y0;
|
|
|
double cp4 = CrossProduct(v1, p);
|
|
|
|
|
|
if ((cp1 * cp2 < 0) && (cp3 * cp4 < 0)) {
|
|
|
// 计算交点的坐标
|
|
|
cr.x0 = p1.x0 + (q1.x0 - p1.x0) * cp1 / (cp1 - cp2);
|
|
|
cr.y0 = p1.y0 + (q1.y0 - p1.y0) * cp1 / (cp1 - cp2);
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
} |