//-----------------------------------------------------------------------------+ // Copyright (C), 1998-2007, SH Software Co. Ltd. // = FileName : XRegion 类 // = Version : ver2.0 // = Author : zjq // = CreateDate : 2002-09-09 // = Description: XRegion 定义 // = Maintainers: // //-----------------------------------------------------------------------------+ #include "StdAfx.h" #include "XRegion.h" #include "XScreenDc.h" #include "XSortSideOnVertex.h" DList * XRegion::g_pAllSpaces = NULL; int XRegion::g_nGlobalIndex = 0; static int CompareSideForFind(const XRegionSide *p1, const void *p2) { return (p1 == p2 ? 0 : 1); } XRegion::XRegion() { m_nIndex = g_nGlobalIndex; g_nGlobalIndex++; } XRegion::~XRegion() { g_nGlobalIndex--; } // 求路径积分的面积 // Modify on 2002/2/22, 当存在误差时,微小的不封闭可能导致巨大的误差。 ads_real XRegion::PathArea() const { int nLen = Length(); if (!nLen) { return 0; } XPoint ptTmp = (*this)[0].GetStartPoint(); XPoint ptBack = ptTmp; ads_real dResult = 0.0; for (int i = 0; i < nLen; i++) { dResult += (*this)[i].PathArea(ptTmp); } if (ptBack.Distance2d(ptTmp) > _DIST_SNAP) { dResult += (ptBack.x - ptTmp.x) * (ptTmp.y + ptBack.y) / 2.0; } return dResult; } //nFlag--0, 内; 1--外 XPoint XRegion::GetPoint(int nFlag, double nDist) const { int nLen = Length(); ASSERT(nLen); const XCurveSegment &seg = (*this)[0]; XPoint ptMid; if (nFlag == 0) { XCurveSegment lCurve = seg.Offset(-nDist, LS_FINITE); ptMid = lCurve.MidPoint(); } else { XCurveSegment rCurve = seg.Offset(nDist, LS_FINITE); ptMid = rCurve.MidPoint(); } return ptMid; } // 得到中心线上的POLYLINE -- Usefull // poly -- result // Status: 没有判断相邻两弧边是否可以并成一条弧边 // 考虑了墙体底标高 //用点是否位于节点范围进行比较 int XRegion::CenterPoly2D(XPoly2D &poly) const { poly.Reset(); int nLen = Length(); if (!nLen) { return RTERROR; } const XRegionSide &wall = (*this)[nLen - 1]; if (nLen == 1 && wall.Is(CURVE_CIRCLE)) // 分成两个半圆 { ASSERT(0); //不考虑圆墙 } else { poly.SetFlag(1); XCurveSegment lastSeg = wall; lastSeg.SetLineFlag(LS_INFINITE); XPoint spt = (*this)[0].GetStartPoint(); // 房间的绕向由第一个墙的方向确定 XPoint ptNext; for (int i = 0; i < nLen; i++) { const XRegionSide &curWall = (*this)[i]; XCurveSegment curSeg = curWall; curSeg.SetLineFlag(LS_INFINITE); spt.z = curWall.GetEndPoint().z; XPoint ept = curWall.GetStartNode()->Include(spt) ? curWall.GetEndPoint() : curWall.GetStartPoint(); XPoint pt1, pt2, ptCur; if (!i) // 求当前点 { int nPtNum = curSeg.Intersection(lastSeg, pt1, pt2); if (nPtNum == 2) { ptCur = XLine(pt1,pt2).NearPoint(spt); } else if (nPtNum == 1) { ptCur = pt1; } else { ptCur = curSeg.NearPoint(spt); // 同一方向上, 两段衔接. } } else { ptCur = ptNext; //上次求得的下一点 } // 求下一个端点 int nNextIndex = i >= nLen-1 ? 0 : i + 1; // 当前段为最后时, 下一段为起始段 const XRegionSide &nextWall = (*this)[nNextIndex]; XCurveSegment nextSeg = nextWall; nextSeg.SetLineFlag(LS_INFINITE); int nPtNum = curSeg.Intersection(nextSeg, pt1, pt2); if (nPtNum == 2) { ptNext = XLine(pt1, pt2).NearPoint(ept); } else if (nPtNum == 1) { ptNext = pt1; } else { ptNext = curSeg.NearPoint(ept); // 同一方向上, 两段衔接. } //添一段 poly.Append(new XPoint(ptCur)); if (curSeg.Is(CURVE_LINE)) { poly.AppendBugle(0.0); } else if (curSeg.Is(CURVE_ARC)) { XArc arc = curSeg.GetArc(); if (spt == curWall.GetStartPoint()) //逆时针 { arc.SetStarAngle(ads_angle(arc.GetCenterPt(), ptCur)); arc.SetEndAngle(ads_angle(arc.GetCenterPt(), ptNext)); poly.AppendBugle(arc.Bulge()); } else { arc.SetEndAngle(ads_angle(arc.GetCenterPt(), ptCur)); arc.SetStarAngle(ads_angle(arc.GetCenterPt(), ptNext)); poly.AppendBugle(-arc.Bulge()); } } else { XGeLib::adsout << _T("\nFetal error!"); assert(0); } spt = ept; lastSeg = curSeg; } } return RTNORM; } int XRegion::ShowMe() const { ads_redraw(NULL,0); XScreenDc dc(1, 1); int nLen = Length(); for (int i = 0; i < nLen; i++) { dc << (*this)[i]; } return RTNORM; } //求房间中心线的界限 int XRegion::GetExtend(XPoint &ptLow, XPoint &ptUp) const { if (!Length()) { return RTERROR; } for (int i = 0; i < Length(); i++) { const XRegionSide &wall = (*this)[i]; if (i == 0) { wall.GetExtend(ptLow, ptUp); } else { XPoint ptMin, ptMax; wall.GetExtend(ptMin, ptMax); ptLow = Min(ptLow, ptMin); ptUp = Max(ptUp, ptMax); } } return RTNORM; } // 比较是否相反 BOOL XRegion::IsEqualTo(const XRegion ®ion) const { const XRegion ®ionThis = *this; int nSideNum = Length(); if (nSideNum != region.Length()) { return FALSE; } for (int i = 0; i < nSideNum; i++) { const XRegionSide &side1 = regionThis[i]; const XRegionSide &side2 = region[i]; if (&side1 != &side2) { return FALSE; } } return TRUE; } // 比较是否相邻 BOOL XRegion::IsAdjacentTo(const XRegion ®ion) const { const XRegion ®ionThis = *this; int nSideNum = Length(); for (int i = 0; i < nSideNum; i++) { const XRegionSide &side1 = regionThis[i]; if (((XRegion &)region).FindNode(&side1, CompareSideForFind)) { return TRUE; } } return FALSE; }