//-----------------------------------------------------------------------------+ // 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;iReverse(); TGRegionEx2D *pHole = new TGRegionEx2D(pNewCurve,false); if (face0.IsInclude(*pHole)) { holes.AddTail(pHole); } else { delete pHole; return false; } } } else { for (long i = 0;iReverse(); 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;iSetElev(elev); } } } double TGRegion2D::GetElev() const { long num = GetBoundaryNum(); for (long i = 0;iGetElev(); } } return 0; } void TGRegion2D::TransformBy(const TGMatrix&matrix) { long num = GetBoundaryNum(); for (long i = 0;iTransformBy(matrix); } } } bool TGRegion2D::Offset(double offset) { long num = GetBoundaryNum(); for (long i = 0;iOffset(offset)) { return false; } } return true; } bool TGRegion2D::IsBoundaryInter() const { if (!IsHoleExist()) { return false; } TDualPtrList curves; for (long i = 0;i1) { 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= 0) //modify by xlc on 110117 搜索房间时不改变精度(搜索房间时不考虑柱子) { Outline().Cut(obj,in,outList,midList); } else { //add by xlc on 100906 解决部分加粗不显示的问题 TPushMemVar vPrec(g_distZero,1.0e-6); Outline().Cut(obj,in,outList,midList); } } if (in.IsEmpty()) { return; } } else { in << obj.Clone(); } for (long i = 0;iIsClosed() && !pCurve->IsClockwise()) { pCurve->Reverse(); } } } double TGRegion2D::Area() const { if (!IsClosed()) { return 0; } double A = Outline().Area(); for (long i = 0;iAppendHole(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;iReverse(); pFace->AppendHole(pCurve,false); res << pFace; } for (long i = 0;iReverse(); res << new TGRegionEx2D(pCurve,false); } } else if (!face.IsOutlineExist()) { return; } else { TGObjectList aInB,aOutB,aOnB,bInA,bOutA,bOnA; for (long i = 0;iReverse(); 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;iReverse(); 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;iReverse(); TGRegionEx2D *pRight = new TGRegionEx2D(pCurve,false); right << pRight; } else { TGObjectList aInB,aOutB,aOnB,bInA,bOutA,bOnA; for (long i = 0;iReverse(); } 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 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 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); } } } } } }