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

849 lines
20 KiB
C++

This file contains ambiguous Unicode characters!

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

//////////////////////////////////////////////////////////////////////////////
//文件: 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;
}