1185 lines
23 KiB
C++
1185 lines
23 KiB
C++
//-----------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
|
|
// = FileName : TGRegion2D.cpp
|
|
// = Version : ver2.0
|
|
// = Author : xlc
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: 类的定义
|
|
// = Maintainers:
|
|
//
|
|
//-----------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "TGRegion2D.h"
|
|
#include "TPGeCurve2D.h"
|
|
#include "TGRegionEx2D.h"
|
|
#include "TGPolygonEx2D.h"
|
|
#include "TGPolygon2D.h"
|
|
#include "TPGeGraph.h"
|
|
#include "TPushMemVar.h"
|
|
#include "TProductid.h"
|
|
|
|
extern int g_nProductId;
|
|
|
|
IMPLEMENT_RUN_TIME_CLASS1(TGRegion2D,"TGRegion2D",TGObject2D)
|
|
|
|
TGRegion2D::~TGRegion2D()
|
|
{
|
|
|
|
}
|
|
|
|
bool TGRegion2D::IsValid() const
|
|
{
|
|
if (GetBoundaryNum()<1)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (IsOutlineExist())
|
|
{
|
|
TPGeCurve2D&curve0 = Outline();
|
|
if (!curve0.IsValid() || curve0.IsSelfCross() ||
|
|
!(curve0.IsInfinite() || (curve0.IsClosed() && !curve0.IsClockwise())))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!IsHoleExist())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
TGObjectList holes;
|
|
if (IsOutlineExist())
|
|
{
|
|
TGRegionEx2D face0(Outline(),false);
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
if (GetBoundary(i+1) == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TPGeCurve2D& curve1 = Hole(i);
|
|
if (!curve1.IsValid() || curve1.IsSelfCross() ||
|
|
!(curve1.IsInfinite() || (curve1.IsClosed() && curve1.IsClockwise())))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TPGeCurve2D* pNewCurve = (TPGeCurve2D*)curve1.Clone();
|
|
pNewCurve->Reverse();
|
|
TGRegionEx2D *pHole = new TGRegionEx2D(pNewCurve,false);
|
|
if (face0.IsInclude(*pHole))
|
|
{
|
|
holes.AddTail(pHole);
|
|
}
|
|
else
|
|
{
|
|
delete pHole;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
if (GetBoundary(i+1) == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TPGeCurve2D& curve1 = Hole(i);
|
|
if (!curve1.IsValid() || curve1.IsSelfCross() ||
|
|
!(curve1.IsInfinite() || (curve1.IsClosed() && curve1.IsClockwise())))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TPGeCurve2D* pNewCurve = (TPGeCurve2D*)curve1.Clone();
|
|
pNewCurve->Reverse();
|
|
holes << new TGRegionEx2D(pNewCurve,false);
|
|
}
|
|
}
|
|
|
|
TGObjectList buf;
|
|
while(holes.GetLength()>1)
|
|
{
|
|
TGRegion2D *pFirst = (TGRegion2D*)(holes.Fetch(0));
|
|
buf << pFirst;
|
|
for (holes.MoveToFirst();!holes.IsOut();holes.MoveToNext())
|
|
{
|
|
if (pFirst->Inter(holes.GetCurRegion2D(),buf))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return IsAllowBoundaryInter()?true:!IsBoundaryInter();
|
|
}
|
|
|
|
bool TGRegion2D::IsInclude(const TGObject&obj) const
|
|
{
|
|
if (IS_CLASS(&obj,TGRegion2D))
|
|
{
|
|
TGObjectList left;
|
|
((const TGRegion2D&)obj).SubtractBy(*this,left);
|
|
return left.IsEmpty();
|
|
}
|
|
TGObjectList in,out;
|
|
Clip(obj,in,out,in);
|
|
return out.IsEmpty();
|
|
}
|
|
|
|
void TGRegion2D::SetElev(double elev)
|
|
{
|
|
long num = GetBoundaryNum();
|
|
for (long i = 0;i<num;i++)
|
|
{
|
|
TPGeCurve2D*pCurve = GetBoundary(i);
|
|
if (pCurve != NULL)
|
|
{
|
|
pCurve->SetElev(elev);
|
|
}
|
|
}
|
|
}
|
|
|
|
double TGRegion2D::GetElev() const
|
|
{
|
|
long num = GetBoundaryNum();
|
|
for (long i = 0;i<num;i++)
|
|
{
|
|
TPGeCurve2D*pCurve = GetBoundary(i);
|
|
if (pCurve != NULL)
|
|
{
|
|
return pCurve->GetElev();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void TGRegion2D::TransformBy(const TGMatrix&matrix)
|
|
{
|
|
long num = GetBoundaryNum();
|
|
for (long i = 0;i<num;i++)
|
|
{
|
|
TPGeCurve2D* pCurve = GetBoundary(i);
|
|
if (pCurve != NULL)
|
|
{
|
|
pCurve->TransformBy(matrix);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TGRegion2D::Offset(double offset)
|
|
{
|
|
long num = GetBoundaryNum();
|
|
for (long i = 0;i<num;i++)
|
|
{
|
|
TPGeCurve2D* pCurve = GetBoundary(i);
|
|
if (pCurve != NULL && !pCurve->Offset(offset))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TGRegion2D::IsBoundaryInter() const
|
|
{
|
|
if (!IsHoleExist())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TDualPtrList<TPGeCurve2D*> curves;
|
|
for (long i = 0;i<GetBoundaryNum();i++)
|
|
{
|
|
TPGeCurve2D* pCurve = GetBoundary(i);
|
|
if (pCurve != NULL)
|
|
{
|
|
curves << GetBoundary(i);
|
|
}
|
|
}
|
|
|
|
TGObjectList buf;
|
|
while(curves.GetLength()>1)
|
|
{
|
|
curves.MoveToFirst();
|
|
TPGeCurve2D *pCurve0 = curves.GetCurData();
|
|
curves.DelCur();
|
|
|
|
for (curves.MoveToFirst();!curves.IsOut();curves.MoveToNext())
|
|
{
|
|
if (pCurve0->Intersect(*curves.GetCurData(),buf))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
GRelation TGRegion2D::HitTest(const TGPoint&pt) const
|
|
{
|
|
if (IsOutlineExist())
|
|
{
|
|
GRelation r = Outline().HitTest(pt);
|
|
if (r.Is(GR_OUTSIDE))
|
|
{
|
|
return GR_OUT;
|
|
}
|
|
else if (r.Is(GR_IN))
|
|
{
|
|
return GR_IN|GR_EDGE;
|
|
}
|
|
}
|
|
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
GRelation r = Hole(i).HitTest(pt);
|
|
if (r.Is(GR_INSIDE))
|
|
{
|
|
return GR_OUT|GR_HOLE;
|
|
}
|
|
else if (r.Is(GR_IN))
|
|
{
|
|
return GR_IN|GR_EDGE|GR_HOLE;
|
|
}
|
|
}
|
|
return GR_IN;
|
|
}
|
|
|
|
void TGRegion2D::Clip(const TGObject &obj,TGObjectList&inList,TGObjectList&outList,TGObjectList&midList) const
|
|
{
|
|
TGObjectList in;
|
|
if (IsOutlineExist())
|
|
{
|
|
// modify by xlc on 110610 区分日照,影响速度
|
|
if (g_nProductId == kTSUN)
|
|
{
|
|
Outline().Cut(obj,in,outList,midList);
|
|
}
|
|
else
|
|
{
|
|
struct resbuf rb;
|
|
acedGetVar(_T("CMDNAMES"),&rb);
|
|
CString sCmd = rb.resval.rstring;
|
|
acutDelString(rb.resval.rstring);
|
|
sCmd.MakeUpper();
|
|
if (sCmd.Find(_T("TUPDSPACE")) >= 0) //modify by xlc on 110117 搜索房间时不改变精度(搜索房间时不考虑柱子)
|
|
{
|
|
Outline().Cut(obj,in,outList,midList);
|
|
}
|
|
else
|
|
{
|
|
//add by xlc on 100906 解决部分加粗不显示的问题
|
|
TPushMemVar<double> vPrec(g_distZero,1.0e-6);
|
|
Outline().Cut(obj,in,outList,midList);
|
|
}
|
|
}
|
|
|
|
if (in.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
in << obj.Clone();
|
|
}
|
|
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
TGObjectList in1;
|
|
in1.Conbine(in);
|
|
in1.CutBy(Hole(i),outList,in,midList);
|
|
}
|
|
|
|
inList.Conbine(in);
|
|
}
|
|
|
|
bool TGRegion2D::Intersect(const TGObject&obj,TGObjectList&res) const
|
|
{
|
|
if (IS_CLASS(&obj,TGRegion2D))
|
|
{
|
|
return Inter((const TGRegion2D&)obj,res);
|
|
}
|
|
|
|
TGObjectList out,in;
|
|
Clip(obj,in,out,in);
|
|
if (in.IsEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
res.Conbine(in);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool TGRegion2D::GetExtend2D(TPGeExtend2D&ext) const
|
|
{
|
|
if (IsOutlineExist())
|
|
{
|
|
return Outline().GetExtend2D(ext);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void TGRegion2D::SubtractBy(const TGObjectList&faces,TGObjectList&res) const
|
|
{
|
|
TGObject*const*pCur = faces.GetFirst();
|
|
if (pCur == NULL)
|
|
{
|
|
res << Clone();
|
|
return;
|
|
}
|
|
|
|
const TGRegion2D& face = (const TGRegion2D&)(**pCur);
|
|
TGObjectList buf;
|
|
SubtractBy(face,buf);
|
|
if (buf.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (pCur = faces.GetNext(pCur);pCur != NULL;pCur = faces.GetNext(pCur))
|
|
{
|
|
TGObjectList buf1;
|
|
const TGRegion2D&face = (const TGRegion2D&)(**pCur);
|
|
for (buf.MoveToFirst();!buf.IsOut();buf.MoveToNext())
|
|
{
|
|
buf.GetCurRegion2D().SubtractBy(face,buf1);
|
|
}
|
|
|
|
if (buf1.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
buf.Clear();
|
|
buf.Conbine(buf1);
|
|
}
|
|
res.Conbine(buf);
|
|
}
|
|
|
|
void TGRegion2D::Normalize()
|
|
{
|
|
if (IsClosed() && Outline().IsClockwise())
|
|
{
|
|
Outline().Reverse();
|
|
}
|
|
|
|
for (long i = 1;i<GetBoundaryNum();i++)
|
|
{
|
|
TPGeCurve2D* pCurve = GetBoundary(i);
|
|
if (pCurve != NULL && pCurve->IsClosed() && !pCurve->IsClockwise())
|
|
{
|
|
pCurve->Reverse();
|
|
}
|
|
}
|
|
}
|
|
|
|
double TGRegion2D::Area() const
|
|
{
|
|
if (!IsClosed())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
double A = Outline().Area();
|
|
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
A -= Hole(i).Area();
|
|
}
|
|
return A;
|
|
}
|
|
|
|
TGPolygon2D* TGRegion2D::MLinearize(double paDist) const
|
|
{
|
|
if (!IsClosed())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (IsHoleExist())
|
|
{
|
|
TGMLine2D* pMLine = Outline().MLinearize(paDist);
|
|
TGPolygonEx2D *pFace = new TGPolygonEx2D(*pMLine,false);
|
|
delete pMLine;
|
|
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
pFace->AppendHole(Hole(i).MLinearize(paDist),false);
|
|
}
|
|
return pFace;
|
|
}
|
|
else
|
|
{
|
|
TGMLine2D* pMLine = Outline().MLinearize(paDist);
|
|
TGPolygon2D *pFace = new TGPolygon2D(*pMLine,false);
|
|
delete pMLine;
|
|
return pFace;
|
|
}
|
|
}
|
|
|
|
bool TGRegion2D::Explode(TGObjectList&res) const
|
|
{
|
|
TGPolygon2D* pPoly = MLinearize();
|
|
if (pPoly == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
res << pPoly;
|
|
return true;
|
|
}
|
|
|
|
bool TGRegion2D::Inter(const TGRegion2D&face,TGObjectList&res) const
|
|
{
|
|
if (!IsMayBoundaryInter() && !face.IsMayBoundaryInter())
|
|
{
|
|
if (!IsOutlineExist())
|
|
{
|
|
res << face.Clone();
|
|
return true;
|
|
}
|
|
else if (!face.IsOutlineExist())
|
|
{
|
|
res << Clone();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
TGObjectList aInB,aOutB,aOnB,bInA,bOutA,bOnA;
|
|
for (long i = 0;i<GetBoundaryNum();i++)
|
|
{
|
|
face.Clip(*GetBoundary(i),aInB,aOutB,aOnB);
|
|
}
|
|
for (i = 0;i<face.GetBoundaryNum();i++)
|
|
{
|
|
Clip(*face.GetBoundary(i),bInA,bOutA,bOnA);
|
|
}
|
|
|
|
if (bOutA.IsEmpty() && aInB.IsEmpty())
|
|
{
|
|
res << face.Clone();
|
|
return true;
|
|
}
|
|
else if (aOutB.IsEmpty() && bInA.IsEmpty())
|
|
{
|
|
res << Clone();
|
|
return true;
|
|
}
|
|
else if (aInB.IsEmpty() || bInA.IsEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
TGObjectList list,buf;
|
|
list.Conbine(aInB);
|
|
list.Conbine(bInA);
|
|
list.Conbine(aOnB);
|
|
|
|
if (Outline().IsClosed() && face.Outline().IsClosed())
|
|
{
|
|
CreateRegion2D(list,res,IsHoleExist() || face.IsHoleExist());
|
|
}
|
|
else
|
|
{
|
|
CreateRegion2DEx(list,res,IsHoleExist() || face.IsHoleExist());
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
else if (IsHoleExist())
|
|
{
|
|
TGObjectList buf;
|
|
if (IsOutlineExist())
|
|
{
|
|
if (!TGRegionEx2D(Outline(),false).Inter(face,buf))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
buf.AddTail(face.Clone());
|
|
}
|
|
|
|
TGObjectList holes;
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
holes << new TGRegionEx2D(Hole(i),false);
|
|
holes.GetCurRegion2D().Outline().Reverse();
|
|
}
|
|
|
|
TGObjectList buf1;
|
|
for (buf.MoveToFirst();!buf.IsOut();buf.MoveToNext())
|
|
{
|
|
buf.GetCurRegion2D().SubtractBy(holes,buf1);
|
|
}
|
|
|
|
if (buf1.IsEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
res.Conbine(buf1);
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return face.Inter(*this,res);
|
|
}
|
|
}
|
|
|
|
void TGRegion2D::SubtractBy(const TGRegion2D&face,TGObjectList&res) const
|
|
{
|
|
if (!IsMayBoundaryInter() && !face.IsMayBoundaryInter())
|
|
{
|
|
if (!IsOutlineExist())
|
|
{
|
|
if (face.IsOutlineExist())
|
|
{
|
|
TGRegionEx2D *pFace = new TGRegionEx2D;
|
|
TPGeCurve2D *pCurve = (TPGeCurve2D*)(face.Outline().Clone());
|
|
pCurve->Reverse();
|
|
pFace->AppendHole(pCurve,false);
|
|
res << pFace;
|
|
}
|
|
for (long i = 0;i<face.GetHoleNum();i++)
|
|
{
|
|
TPGeCurve2D *pCurve = (TPGeCurve2D*)(face.Hole(i).Clone());
|
|
pCurve->Reverse();
|
|
res << new TGRegionEx2D(pCurve,false);
|
|
}
|
|
}
|
|
else if (!face.IsOutlineExist())
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
TGObjectList aInB,aOutB,aOnB,bInA,bOutA,bOnA;
|
|
for (long i = 0;i<GetBoundaryNum();i++)
|
|
{
|
|
face.Clip(*GetBoundary(i),aInB,aOutB,aOnB);
|
|
}
|
|
for (i = 0;i<face.GetBoundaryNum();i++)
|
|
{
|
|
Clip(*face.GetBoundary(i),bInA,bOutA,bOnA);
|
|
}
|
|
|
|
if (aOutB.IsEmpty() && bInA.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
else if (bOutA.IsEmpty() && aInB.IsEmpty())
|
|
{
|
|
TGObjectList list;
|
|
bInA.ReverseCurve2D();
|
|
list.Conbine(bInA);
|
|
list.Conbine(aOutB);
|
|
list.Conbine(aOnB);
|
|
if (Outline().IsClosed() && face.Outline().IsClosed())
|
|
{
|
|
CreateRegion2D(list,res,true);
|
|
}
|
|
else
|
|
{
|
|
CreateRegion2DEx(list,res,true);
|
|
}
|
|
}
|
|
else if (aInB.IsEmpty() || bInA.IsEmpty())
|
|
{
|
|
res << Clone();
|
|
}
|
|
else
|
|
{
|
|
TGObjectList list;
|
|
bInA.ReverseCurve2D();
|
|
list.Conbine(bInA);
|
|
list.Conbine(aOutB);
|
|
list.Conbine(aOnB);
|
|
if (Outline().IsClosed() && face.Outline().IsClosed())
|
|
{
|
|
CreateRegion2D(list,res,IsHoleExist() || face.IsHoleExist());
|
|
}
|
|
else
|
|
{
|
|
CreateRegion2DEx(list,res,IsHoleExist() || face.IsHoleExist());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (face.IsHoleExist())
|
|
{
|
|
if (face.IsOutlineExist())
|
|
{
|
|
SubtractBy(TGRegionEx2D(face.Outline(),false),res);
|
|
}
|
|
|
|
for (long i = 0;i<face.GetHoleNum();i++)
|
|
{
|
|
TGRegionEx2D hFace(face.Hole(i),false);
|
|
hFace.Outline().Reverse();
|
|
Inter(hFace,res);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TGObjectList buf;
|
|
TGRegionEx2D region0;
|
|
if (IsOutlineExist())
|
|
{
|
|
region0.SetOutline((TPGeCurve2D*)Outline().Clone(),false);
|
|
}
|
|
region0.SubtractBy(face,buf);
|
|
if (buf.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
TGObjectList holes;
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
holes << new TGRegionEx2D(Hole(i),false);
|
|
holes.GetCurRegion2D().Outline().Reverse();
|
|
}
|
|
|
|
buf.MoveToFirst();
|
|
if (buf.GetCurRegion2D().IsHoleExist())
|
|
{
|
|
holes.Union(face);
|
|
|
|
TGRegionEx2D *pRes = new TGRegionEx2D(Outline(),false);
|
|
for (holes.MoveToFirst();!holes.IsOut();holes.MoveToNext())
|
|
{
|
|
TPGeCurve2D* pCurve = (TPGeCurve2D*)(holes.GetCurRegion2D().Outline().Clone());
|
|
pCurve->Reverse();
|
|
pRes->AppendHole(pCurve,false);
|
|
}
|
|
res << pRes;
|
|
}
|
|
else
|
|
{
|
|
for (buf.MoveToFirst();!buf.IsOut();buf.MoveToNext())
|
|
{
|
|
buf.GetCurRegion2D().SubtractBy(holes,res);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TGRegion2D* TGRegion2D::Union(const TGRegion2D&face) const
|
|
{
|
|
if (!IsMayBoundaryInter() && !face.IsMayBoundaryInter())
|
|
{
|
|
if (!IsOutlineExist())
|
|
{
|
|
return (TGRegion2D*)Clone();
|
|
}
|
|
else if (!face.IsOutlineExist())
|
|
{
|
|
return (TGRegion2D*)face.Clone();
|
|
}
|
|
else
|
|
{
|
|
TGObjectList aInB,aOutB,aOnB,bInA,bOutA,bOnA;
|
|
for (long i = 0;i<GetBoundaryNum();i++)
|
|
{
|
|
face.Clip(*GetBoundary(i),aInB,aOutB,aOnB);
|
|
}
|
|
for (i = 0;i<face.GetBoundaryNum();i++)
|
|
{
|
|
Clip(*face.GetBoundary(i),bInA,bOutA,bOnA);
|
|
}
|
|
|
|
if (bOutA.IsEmpty() && aInB.IsEmpty())
|
|
{
|
|
return (TGRegion2D*)Clone();
|
|
}
|
|
else if (aOutB.IsEmpty() && bInA.IsEmpty())
|
|
{
|
|
return (TGRegion2D*)face.Clone();
|
|
}
|
|
else if (aInB.IsEmpty() || bInA.IsEmpty())
|
|
{
|
|
if (aOnB.IsEmpty())
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
TGObjectList list,res;
|
|
list.Conbine(aOutB);
|
|
list.Conbine(bOutA);
|
|
if (Outline().IsClosed() && face.Outline().IsClosed())
|
|
{
|
|
CreateRegion2D(list,res,true);
|
|
}
|
|
else
|
|
{
|
|
CreateRegion2DEx(list,res,true);
|
|
}
|
|
return (TGRegion2D*)res.Fetch(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TGObjectList list,res;
|
|
list.Conbine(aOutB);
|
|
list.Conbine(bOutA);
|
|
list.Conbine(aOnB);
|
|
if (Outline().IsClosed() && face.Outline().IsClosed())
|
|
{
|
|
CreateRegion2D(list,res,true);
|
|
}
|
|
else
|
|
{
|
|
CreateRegion2DEx(list,res,true);
|
|
}
|
|
return (TGRegion2D*)res.Fetch(0);
|
|
}
|
|
}
|
|
}
|
|
else if (IsHoleExist())
|
|
{
|
|
TGRegion2D *pU0;
|
|
if (IsOutlineExist())
|
|
{
|
|
pU0 = TGRegionEx2D(Outline(),false).Union(face);
|
|
if (pU0 == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pU0 = new TGRegionEx2D;
|
|
}
|
|
|
|
TGObjectList holes;
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
TGRegionEx2D hFace(Hole(i),false);
|
|
hFace.Outline().Reverse();
|
|
hFace.SubtractBy(face,holes);
|
|
}
|
|
|
|
if (holes.IsEmpty())
|
|
{
|
|
return pU0;
|
|
}
|
|
else
|
|
{
|
|
TGRegionEx2D*pU1;
|
|
if (IS_TYPE(pU0,TGRegionEx2D))
|
|
{
|
|
pU1 = (TGRegionEx2D*)pU0;
|
|
}
|
|
else
|
|
{
|
|
pU1 = new TGRegionEx2D(*pU0);
|
|
delete pU0;
|
|
}
|
|
|
|
for (holes.MoveToFirst();!holes.IsOut();holes.MoveToNext())
|
|
{
|
|
TGRegion2D&hHole = holes.GetCurRegion2D();
|
|
if (hHole.IsHoleExist())
|
|
{
|
|
delete pU1;
|
|
return NULL;
|
|
}
|
|
|
|
TPGeCurve2D*pCurve = (TPGeCurve2D*)hHole.Outline().Clone();
|
|
pCurve->Reverse();
|
|
pU1->AppendHole(pCurve,false);
|
|
}
|
|
return pU1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return face.Union(*this);
|
|
}
|
|
}
|
|
|
|
void TGRegion2D::CutBy(const TPGeCurve2D&curve,TGObjectList&left,TGObjectList&right) const
|
|
{
|
|
if (IsMayBoundaryInter())
|
|
{
|
|
TGObjectList lBuf,rBuf;
|
|
TGRegionEx2D region0;
|
|
if (IsOutlineExist())
|
|
{
|
|
region0.SetOutline((TPGeCurve2D*)Outline().Clone(),false);
|
|
}
|
|
region0.CutBy(curve,lBuf,rBuf);
|
|
if (lBuf.IsEmpty())
|
|
{
|
|
right << Clone();
|
|
}
|
|
else if (rBuf.IsEmpty())
|
|
{
|
|
left << Clone();
|
|
}
|
|
else
|
|
{
|
|
TGObjectList lHole,rHole;
|
|
for (long i = 0;i<GetHoleNum();i++)
|
|
{
|
|
TGRegionEx2D hFace(Hole(i),false);
|
|
hFace.Outline().Reverse();
|
|
hFace.CutBy(curve,lHole,rHole);
|
|
}
|
|
|
|
for (lBuf.MoveToFirst();!lBuf.IsOut();lBuf.MoveToNext())
|
|
{
|
|
lBuf.GetCurRegion2D().SubtractBy(lHole,left);
|
|
}
|
|
for (rBuf.MoveToFirst();!rBuf.IsOut();rBuf.MoveToNext())
|
|
{
|
|
rBuf.GetCurRegion2D().SubtractBy(rHole,right);
|
|
}
|
|
}
|
|
}
|
|
else if (!IsOutlineExist())
|
|
{
|
|
TGRegionEx2D *pLeft = new TGRegionEx2D(curve,false);
|
|
left << pLeft;
|
|
TPGeCurve2D *pCurve = (TPGeCurve2D*)curve.Clone();
|
|
pCurve->Reverse();
|
|
TGRegionEx2D *pRight = new TGRegionEx2D(pCurve,false);
|
|
right << pRight;
|
|
}
|
|
else
|
|
{
|
|
TGObjectList aInB,aOutB,aOnB,bInA,bOutA,bOnA;
|
|
for (long i = 0;i<GetBoundaryNum();i++)
|
|
{
|
|
curve.Cut(*GetBoundary(i),bInA,bOutA,bOnA);
|
|
}
|
|
Clip(curve,aInB,aOutB,aOnB);
|
|
|
|
if (bOutA.IsEmpty() && aInB.IsEmpty())
|
|
{
|
|
left << Clone();
|
|
}
|
|
else if (curve.IsClosed() && aOutB.IsEmpty() && bInA.IsEmpty())
|
|
{
|
|
bool bClockwise = curve.IsClockwise();
|
|
TPGeCurve2D*pNewCurve = (TPGeCurve2D*)curve.Clone();
|
|
if (bClockwise)
|
|
{
|
|
pNewCurve->Reverse();
|
|
}
|
|
left << new TGRegionEx2D(pNewCurve,false);
|
|
TGObjectList rList;
|
|
if (!bClockwise)
|
|
{
|
|
aInB.ReverseCurve2D();
|
|
}
|
|
|
|
rList.Conbine(aInB);
|
|
rList.Conbine(bOutA);
|
|
rList.Conbine(bOnA);
|
|
if (Outline().IsClosed())
|
|
{
|
|
CreateRegion2D(rList,right,true);
|
|
}
|
|
else
|
|
{
|
|
CreateRegion2DEx(rList,right,true);
|
|
}
|
|
}
|
|
else if (aInB.IsEmpty() || bInA.IsEmpty())
|
|
{
|
|
right << Clone();
|
|
}
|
|
else
|
|
{
|
|
bool bFinite = Outline().IsClosed();
|
|
|
|
TGObjectList lList,temp(aInB);
|
|
bool bClockwise = curve.IsClosed() && curve.IsClockwise();
|
|
if (bClockwise)
|
|
{
|
|
temp.ReverseCurve2D();
|
|
aOnB.ReverseCurve2D();
|
|
}
|
|
lList.Conbine(temp);
|
|
lList.Conbine(bInA);
|
|
lList.Conbine(aOnB);
|
|
if (bFinite)
|
|
{
|
|
CreateRegion2D(lList,left,IsHoleExist());
|
|
}
|
|
else
|
|
{
|
|
CreateRegion2DEx(lList,left,IsHoleExist());
|
|
}
|
|
TGObjectList rList;
|
|
if (!bClockwise)
|
|
{
|
|
aInB.ReverseCurve2D();
|
|
}
|
|
rList.Conbine(aInB);
|
|
rList.Conbine(bOutA);
|
|
rList.Conbine(bOnA);
|
|
if (bFinite)
|
|
{
|
|
CreateRegion2D(rList,right,IsHoleExist());
|
|
}
|
|
else
|
|
{
|
|
CreateRegion2DEx(rList,right,IsHoleExist());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TPGeCurve2D* TGRegion2D::GetBoundary(long i) const
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
long TGRegion2D::GetBoundaryNum() const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
bool TGRegion2D::IsOutlineExist() const
|
|
{
|
|
return GetBoundary(0) != NULL;
|
|
}
|
|
|
|
TPGeCurve2D& TGRegion2D::Outline() const
|
|
{
|
|
return *GetBoundary(0);
|
|
}
|
|
|
|
long TGRegion2D::GetHoleNum() const
|
|
{
|
|
return GetBoundaryNum()-1;
|
|
}
|
|
|
|
bool TGRegion2D::IsHoleExist() const
|
|
{
|
|
return GetBoundaryNum()>1;
|
|
}
|
|
|
|
TPGeCurve2D& TGRegion2D::Hole(long i) const
|
|
{
|
|
return *GetBoundary(i+1);
|
|
}
|
|
|
|
bool TGRegion2D::IsClosed() const
|
|
{
|
|
return IsOutlineExist() && Outline().IsClosed();
|
|
}
|
|
|
|
bool TGRegion2D::IsAllowBoundaryInter() const
|
|
{
|
|
return IsNot(NO_BOUNDARY_INTER);
|
|
}
|
|
|
|
bool TGRegion2D::IsMayBoundaryInter() const
|
|
{
|
|
return IsHoleExist() && (IsAllowBoundaryInter() || !IsClosed());
|
|
}
|
|
|
|
bool TGRegion2D::IsEntirePlane() const
|
|
{
|
|
return !IsHoleExist() && !IsOutlineExist();
|
|
}
|
|
|
|
|
|
void TGRegion2D::CreateRegion2D(TGObjectList &curves,TGObjectList &res,bool bCheckHole)const
|
|
{
|
|
TGObjectList closeCurves;
|
|
for (curves.MoveToFirst(); !curves.IsOut(); curves.MoveToNext())
|
|
{
|
|
TPGeCurve2D* pCurve = (TPGeCurve2D*)curves.GetCurData();
|
|
if (pCurve->IsClosed())
|
|
{
|
|
closeCurves << curves.FetchCur();
|
|
}
|
|
else if (!pCurve->IsCurveSeg())
|
|
{
|
|
curves.DelCur();
|
|
}
|
|
}
|
|
|
|
TPGeGraph g;
|
|
g.AppendEdge(curves);
|
|
g.FindCurve(closeCurves,closeCurves);
|
|
|
|
if (closeCurves.GetLength() == 1 || !bCheckHole)
|
|
{
|
|
for (closeCurves.MoveToFirst(); !closeCurves.IsOut(); closeCurves.MoveToNext())
|
|
{
|
|
res << new TGRegionEx2D((TPGeCurve2D*)closeCurves.FetchCur(),false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TList<TGRegionEx2D*> face;
|
|
for (closeCurves.MoveToFirst(); !closeCurves.IsOut(); closeCurves.MoveToNext())
|
|
{
|
|
TPGeCurve2D* pCurve = (TPGeCurve2D*)closeCurves.GetCurData();
|
|
if (!pCurve->IsClockwise())
|
|
{
|
|
closeCurves.FetchCur();
|
|
|
|
TGRegionEx2D* pFace = new TGRegionEx2D(pCurve,false);
|
|
face << pFace;
|
|
res << pFace;
|
|
}
|
|
}
|
|
|
|
if (face.GetLength() == 1)
|
|
{
|
|
TGRegionEx2D *pFace = face.GetAt(0);
|
|
for (closeCurves.MoveToFirst(); !closeCurves.IsOut(); closeCurves.MoveToNext())
|
|
{
|
|
pFace->AppendHole((TPGeCurve2D*)closeCurves.FetchCur(),false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (face.MoveToFirst(); !face.IsOut(); face.MoveToNext())
|
|
{
|
|
TGRegionEx2D *pFace = face.GetCurData();
|
|
TPGeCurve2D&outline = pFace->Outline();
|
|
|
|
for (closeCurves.MoveToFirst(); !closeCurves.IsOut(); closeCurves.MoveToNext())
|
|
{
|
|
GRelation r = outline.HitTest(closeCurves.GetCurPData().GetSamplePoint());
|
|
if (r.Is(GR_INSIDE))
|
|
{
|
|
pFace->AppendHole((TPGeCurve2D*)closeCurves.FetchCur(),false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TGRegion2D::CreateRegion2DEx(TGObjectList &curves,TGObjectList &res,bool bCheckHole)const
|
|
{
|
|
TGObjectList closeCurves,infiniteCurves;
|
|
for (curves.MoveToFirst(); !curves.IsOut(); curves.MoveToNext())
|
|
{
|
|
TPGeCurve2D* pCurve = (TPGeCurve2D*)curves.GetCurData();
|
|
if (pCurve->IsClosed())
|
|
{
|
|
closeCurves << curves.FetchCur();
|
|
}
|
|
else if (!pCurve->IsFinite(true) && !pCurve->IsFinite(false))
|
|
{
|
|
infiniteCurves << curves.FetchCur();
|
|
}
|
|
}
|
|
|
|
TPGeGraph g;
|
|
g.AppendEdge(curves);
|
|
g.FindCurve(closeCurves,infiniteCurves);
|
|
|
|
TList<TGRegionEx2D*> face;
|
|
if (infiniteCurves.GetLength() == 2)
|
|
{
|
|
TPGeCurve2D *pCurve0 = (TPGeCurve2D*)infiniteCurves.Fetch(0);
|
|
TPGeCurve2D *pCurve1 = (TPGeCurve2D*)infiniteCurves.Fetch(0);
|
|
|
|
if (pCurve0->HitTest(pCurve1->GetSamplePoint()).Is(GR_RIGHT)
|
|
&& pCurve1->HitTest(pCurve0->GetSamplePoint()).Is(GR_RIGHT))
|
|
{
|
|
TGRegionEx2D* pRegion0 = new TGRegionEx2D(pCurve0,false);
|
|
TGRegionEx2D* pRegion1 = new TGRegionEx2D(pCurve1,false);
|
|
|
|
res << pRegion0 << pRegion1;
|
|
face << pRegion0 << pRegion1;
|
|
}
|
|
else
|
|
{
|
|
TGRegionEx2D *pRegion = new TGRegionEx2D(pCurve0,false);
|
|
pRegion->AppendHole(pCurve1,false);
|
|
res << pRegion;
|
|
face << pRegion;
|
|
}
|
|
}
|
|
else if (infiniteCurves.GetLength() == 1)
|
|
{
|
|
TGRegionEx2D *pRegion = new TGRegionEx2D((TPGeCurve2D*)infiniteCurves.Fetch(0),false);
|
|
res << pRegion;
|
|
face << pRegion;
|
|
}
|
|
|
|
if (!bCheckHole)
|
|
{
|
|
for (closeCurves.MoveToFirst(); !closeCurves.IsOut(); closeCurves.MoveToNext())
|
|
{
|
|
res << new TGRegionEx2D((TPGeCurve2D*)closeCurves.FetchCur(),false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (closeCurves.MoveToFirst(); !closeCurves.IsOut(); closeCurves.MoveToNext())
|
|
{
|
|
TPGeCurve2D* pCurve = (TPGeCurve2D*)closeCurves.GetCurData();
|
|
if (!pCurve->IsClockwise())
|
|
{
|
|
closeCurves.FetchCur();
|
|
|
|
TGRegionEx2D* pRegion = new TGRegionEx2D(pCurve,false);
|
|
face << pRegion;
|
|
res << pRegion;
|
|
}
|
|
}
|
|
|
|
if (face.IsEmpty() && !closeCurves.IsEmpty())
|
|
{
|
|
TGRegionEx2D *pRegion = new TGRegionEx2D;
|
|
face << pRegion;
|
|
res << pRegion;
|
|
}
|
|
|
|
if (face.GetLength() == 1)
|
|
{
|
|
TGRegionEx2D *pFace = face.GetAt(0);
|
|
for (closeCurves.MoveToFirst(); !closeCurves.IsOut(); closeCurves.MoveToNext())
|
|
{
|
|
pFace->AppendHole((TPGeCurve2D*)closeCurves.FetchCur(),false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (face.MoveToFirst(); !face.IsOut(); face.MoveToNext())
|
|
{
|
|
TGRegionEx2D *pFace = face.GetCurData();
|
|
TPGeCurve2D&outline = pFace->Outline();
|
|
|
|
for (closeCurves.MoveToFirst(); !closeCurves.IsOut(); closeCurves.MoveToNext())
|
|
{
|
|
GRelation r = outline.HitTest(closeCurves.GetCurPData().GetSamplePoint());
|
|
if (r.Is(GR_INSIDE))
|
|
{
|
|
pFace->AppendHole((TPGeCurve2D*)closeCurves.FetchCur(),false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |