611 lines
13 KiB
C++
611 lines
13 KiB
C++
//-----------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
|
|
// = FileName : TSearchRegionFromCurve 类
|
|
// = Version : ver2.0
|
|
// = Author : wlw
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: TSearchRegionFromCurve 定义
|
|
// = Maintainers:
|
|
//
|
|
//-----------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "TSearchRegionFromCurve.h"
|
|
#include "TGGeRegionIndex.h"
|
|
#include "TGGeCurveInline.h"
|
|
|
|
extern int operator & (const TADSGePoint3d &pt0, TGGePoly2D &poly);
|
|
TDPtrList<TSortSideOnVertex> TSearchRegionFromCurve::g_lstAllSortSides;
|
|
TCHAR TSearchRegionFromCurve::s_chConstructed = 0;
|
|
|
|
TSearchRegionFromCurve::TSearchRegionFromCurve()
|
|
{
|
|
_XSearchRegionFromCurve();
|
|
}
|
|
|
|
void TSearchRegionFromCurve::_XSearchRegionFromCurve()
|
|
{
|
|
ASSERT(!s_chConstructed);
|
|
s_chConstructed = 1;
|
|
|
|
TGGeRegionSide::g_pAllWalls = &m_sides;
|
|
TGGeRegion::g_pAllSpaces = &m_regions;
|
|
TGGeRegion::g_nGlobalIndex = 0;
|
|
|
|
g_lstAllSortSides.Reset();
|
|
}
|
|
|
|
// 有曲线集构造排序曲线表
|
|
void TSearchRegionFromCurve::InitStart(const TDPtrList<TGGeCurveSegment> &lstSegs)
|
|
{
|
|
// 构造排序墙
|
|
long nLen = lstSegs.Length();
|
|
int nStep = nLen/100;
|
|
if (nStep < 1)
|
|
{
|
|
nStep = 1;
|
|
}
|
|
|
|
BOOL bEcho = (g_bEchoSearch && nStep >= 2);
|
|
if (bEcho)
|
|
{
|
|
acedSetStatusBarProgressMeter(_T("曲线排序"), 0, nLen);
|
|
}
|
|
|
|
for (long i = 0; i < nLen; i++)
|
|
{
|
|
const TGGeCurveSegment &seg = lstSegs[i];
|
|
if (seg.Is(CURVE_CIRCLE))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (bEcho)
|
|
{
|
|
if (!(i%nStep))
|
|
{
|
|
acedSetStatusBarProgressMeterPos(i);
|
|
}
|
|
}
|
|
|
|
TGGeRegionSide *pSide = new TGGeRegionSide(seg);
|
|
if (!*pSide)
|
|
{
|
|
delete pSide; continue;
|
|
}
|
|
else
|
|
{
|
|
NewAppend(pSide);
|
|
}
|
|
}
|
|
|
|
if (bEcho)
|
|
{
|
|
acedRestoreStatusBar();
|
|
}
|
|
}
|
|
|
|
// 释放全局变量
|
|
TSearchRegionFromCurve::~TSearchRegionFromCurve()
|
|
{
|
|
TGGeRegionSide::g_pAllWalls = NULL;
|
|
TGGeRegion::g_pAllSpaces = NULL;
|
|
TGGeRegion::g_nGlobalIndex = 0;
|
|
|
|
g_lstAllSortSides.Reset();
|
|
s_chConstructed = 0;
|
|
m_sides.Reset();
|
|
m_regions.Reset();
|
|
}
|
|
|
|
TGGeRegionSide *TSearchRegionFromCurve::HitTest(TADSGePoint3d ptMid)
|
|
{
|
|
int num = m_sides.Length();
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
TGGeRegionSide *pSide = m_sides[i];
|
|
TGGeCurveSegment &seg = *pSide;
|
|
|
|
int nPrFlag = (ptMid & seg);
|
|
if (nPrFlag == PR_INSIDE)
|
|
{
|
|
return pSide;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//求最外区域, 返回数目
|
|
// 算法:
|
|
// 1. 取面积最大的区域,一定是外边界
|
|
// 2. 搜索出外边界所包含的各个区域
|
|
// 3. 从总区域中扣除外边界和它内部的区域
|
|
// 4. 如果总区域数不为0,则返回1.
|
|
int TSearchRegionFromCurve::GetOutsideRegions1(TDPtrList<int> &lstOutIndex) const
|
|
{
|
|
TDPtrList<TGGeRegionIndex> lstRegs;
|
|
int nRegionNum = m_regions.Length();
|
|
if (!nRegionNum)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for (int i = 0; i < nRegionNum; i++)
|
|
{
|
|
const TGGeRegion ® = m_regions[i];
|
|
double dPathArea = reg.PathArea();
|
|
|
|
TGGePoly2D polyTemp;
|
|
reg.CenterPoly2D(polyTemp);
|
|
|
|
TADSGePoint3d ptMid = polyTemp.GetInsidePoint();
|
|
|
|
TGGeRegionIndex *pReg = new TGGeRegionIndex(i, dPathArea, ptMid);
|
|
lstRegs.Append(pReg);
|
|
}
|
|
|
|
lstRegs.QuickSort(TGGeRegionIndex::CompareRegion);
|
|
int nTotalRegNum = nRegionNum;
|
|
|
|
while(nRegionNum > 0)
|
|
{
|
|
TGGeRegionIndex *pIdx = lstRegs.Tail();
|
|
lstOutIndex.Append(new int(pIdx->m_nIndex));
|
|
|
|
TGGePoly2D poly2d;
|
|
m_regions[pIdx->m_nIndex].CenterPoly2D(poly2d);
|
|
lstRegs.Remove(nRegionNum-1);
|
|
nRegionNum--;
|
|
|
|
int nStep = nRegionNum / 100;
|
|
if (nStep < 1)
|
|
{
|
|
nStep = 1;
|
|
}
|
|
|
|
if (g_bEchoSearch && nStep > 1)
|
|
{
|
|
acedSetStatusBarProgressMeter(_T("求外边界"), 0, nRegionNum);
|
|
}
|
|
|
|
for (int n = 0; n < nRegionNum; n++)
|
|
{
|
|
if (g_bEchoSearch && nStep > 1 && !(n % nStep))
|
|
{
|
|
acedSetStatusBarProgressMeterPos((nTotalRegNum-nRegionNum));
|
|
}
|
|
|
|
TGGeRegionIndex *pReg = lstRegs[n];
|
|
if ((pReg->m_ptInside&poly2d) == PR_INSIDE)
|
|
{
|
|
lstRegs.Remove();
|
|
n--;
|
|
nRegionNum--;
|
|
}
|
|
}
|
|
|
|
if (g_bEchoSearch && nStep > 1)
|
|
{
|
|
acedRestoreStatusBar();
|
|
}
|
|
}
|
|
|
|
return lstOutIndex.Length();
|
|
}
|
|
|
|
// 在全局边表中添加一项并根据需要构造排序边表
|
|
// Status: 考虑了墙体的底标高
|
|
void TSearchRegionFromCurve::NewAppend(TGGeRegionSide *pSide)
|
|
{
|
|
m_sides.Append(pSide);
|
|
for (int n = 0; n < 2; n++)
|
|
{
|
|
//建立排序表提高速度,R14下速度提高不明显
|
|
TADSGePoint3d &ptVertex = n ? pSide->EndPoint() : pSide->StartPoint();
|
|
|
|
int nVerNum = g_lstAllSortSides.Length();
|
|
|
|
for (int i = 0; i < nVerNum; i++)
|
|
{
|
|
TSortSideOnVertex *pVertex = g_lstAllSortSides[i];
|
|
int nRes = ComparePointBySortXY(&ptVertex, &pVertex->m_ptLoc);
|
|
|
|
if (nRes == 0)
|
|
{
|
|
ptVertex = pVertex->m_ptLoc; //精确相等
|
|
pVertex->Insert(pSide);
|
|
break;
|
|
}
|
|
else if (nRes < 0)
|
|
{ //在i之前插入
|
|
TSortSideOnVertex *pSortSide1 = new TSortSideOnVertex(ptVertex);
|
|
pSortSide1->Insert(pSide);
|
|
g_lstAllSortSides.Insert(pSortSide1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == nVerNum)
|
|
{
|
|
TSortSideOnVertex *pSortSide1 = new TSortSideOnVertex(ptVertex);
|
|
pSortSide1->Insert(pSide);
|
|
g_lstAllSortSides.Append(pSortSide1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 功能: 找所有的空间
|
|
// 并设置外墙标志
|
|
// 返回室外空间
|
|
TGGeRegion * TSearchRegionFromCurve::SearchRegions()
|
|
{
|
|
// 找每边两侧的区域
|
|
int nLen = m_sides.Length();
|
|
|
|
int nStep = nLen / 100;
|
|
if (nStep < 1)
|
|
{
|
|
nStep = 1;
|
|
}
|
|
|
|
if (g_bEchoSearch)
|
|
{
|
|
TCString sMsg(256);
|
|
sMsg << _T("对") << nLen << _T("条边搜索区域");
|
|
acedSetStatusBarProgressMeter(sMsg, 0, nLen);
|
|
}
|
|
|
|
for (int i = 0; i < nLen; i++)
|
|
{
|
|
TGGeRegionSide &aSide = *m_sides[(int)i];
|
|
TSortSideOnVertex *pSortWalls = aSide.GetStartNode();
|
|
|
|
if (!pSortWalls) //当前墙孤立
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (g_bEchoSearch && !(i % nStep))
|
|
{
|
|
acedSetStatusBarProgressMeterPos(i);
|
|
}
|
|
|
|
aSide.g_pCurRegion = NULL;
|
|
if (!aSide.GetLeftRegion())
|
|
{
|
|
aSide.g_pCurRegion = new TGGeRegion;
|
|
aSide.g_pCurRegion->Push(&aSide);
|
|
|
|
if (aSide.Trival(aSide.GetStartNode(), 0) == RTNORM)
|
|
{
|
|
m_regions.Append(aSide.g_pCurRegion);
|
|
int nSideNum = TGGeRegionSide::g_pCurRegion->Length();
|
|
for (int n = 0; n < nSideNum; n++)
|
|
{
|
|
TGGeRegionSide &wl = *(*aSide.g_pCurRegion)[n];
|
|
if (wl.GetCurSide())
|
|
{
|
|
wl.SetRightRegion(aSide.g_pCurRegion);
|
|
}
|
|
else
|
|
{
|
|
wl.SetLeftRegion(aSide.g_pCurRegion);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete TGGeRegionSide::g_pCurRegion;
|
|
TGGeRegionSide::g_pCurRegion = NULL;
|
|
}
|
|
}
|
|
|
|
if (!aSide.GetRighttRegion())
|
|
{
|
|
aSide.g_pCurRegion = new TGGeRegion;
|
|
aSide.g_pCurRegion->Push(&aSide);
|
|
|
|
if (aSide.Trival(aSide.GetStartNode(), 1) == RTNORM)
|
|
{
|
|
m_regions.Append(aSide.g_pCurRegion);
|
|
int nSideNum = TGGeRegionSide::g_pCurRegion->Length();
|
|
|
|
for (int n = 0; n < nSideNum; n++)
|
|
{
|
|
TGGeRegionSide &wl = *(*aSide.g_pCurRegion)[n];
|
|
if (wl.GetCurSide())
|
|
{
|
|
wl.SetRightRegion(aSide.g_pCurRegion);
|
|
}
|
|
else
|
|
{
|
|
wl.SetLeftRegion(aSide.g_pCurRegion);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete TGGeRegionSide::g_pCurRegion;
|
|
TGGeRegionSide::g_pCurRegion = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (g_bEchoSearch)
|
|
{
|
|
acedRestoreStatusBar();
|
|
}
|
|
|
|
// 查找外边的墙
|
|
TGGeRegion *extCell = NULL;
|
|
int nRegionNum = m_regions.Length();
|
|
|
|
if (nRegionNum == 2) // 室内外空间边界重合
|
|
{
|
|
TGGeRegion &sp = *m_regions[0];
|
|
if (sp.PathArea() < 0) // 逆时针
|
|
{
|
|
if (sp[0]->GetRighttRegion() == &sp)
|
|
{
|
|
extCell = &sp;
|
|
}
|
|
else
|
|
{
|
|
extCell = m_regions[1];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sp[0]->GetLeftRegion() == &sp)
|
|
{
|
|
extCell = &sp;
|
|
}
|
|
else
|
|
{
|
|
extCell = m_regions[1];
|
|
}
|
|
}
|
|
}
|
|
else //常规情况, 取面积最大的为
|
|
{
|
|
ads_real dAreaMax = 0.0;
|
|
for (int k = 0; k < nRegionNum; k++)
|
|
{
|
|
TGGeRegion *pRegion = m_regions[k];
|
|
ads_real dCurArea = pRegion->PathArea();
|
|
|
|
if (fabs(dCurArea) > dAreaMax)
|
|
{
|
|
extCell = pRegion;
|
|
dAreaMax = fabs(dCurArea);
|
|
}
|
|
}
|
|
}
|
|
return extCell;
|
|
}
|
|
|
|
// 搜索一墙的左右房间
|
|
// 参数:
|
|
// aWall(IN)--给定的墙
|
|
// lSpace(OUT)--左边的空间
|
|
// rSpace(OUT)--右边的空间
|
|
// 返回: RTNORM/RTERROR
|
|
int TSearchRegionFromCurve::SerachTwoRegion(TGGeRegionSide &aSide,
|
|
TGGeRegion &lRegion, TGGeRegion &rRegion)
|
|
{
|
|
if (!aSide)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
aSide.g_pCurRegion = &lRegion;
|
|
aSide.SetLeftRegion(&lRegion);
|
|
lRegion.Push(&aSide);
|
|
|
|
if (aSide.Trival(aSide.GetStartNode(), 0) != RTNORM)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
int nSideNum = TGGeRegionSide::g_pCurRegion->Length();
|
|
for (int n = 0; n < nSideNum; n++)
|
|
{
|
|
TGGeRegionSide &wl = *(*aSide.g_pCurRegion)[n];
|
|
if (wl.GetCurSide())
|
|
{
|
|
wl.SetRightRegion(aSide.g_pCurRegion);
|
|
}
|
|
else
|
|
{
|
|
wl.SetLeftRegion(aSide.g_pCurRegion);
|
|
}
|
|
}
|
|
|
|
aSide.g_pCurRegion = &rRegion;
|
|
aSide.SetRightRegion(&rRegion);
|
|
rRegion.Push(&aSide);
|
|
|
|
if (aSide.Trival(aSide.GetStartNode(), 1) != RTNORM)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
nSideNum = TGGeRegionSide::g_pCurRegion->Length();
|
|
for (n = 0; n < nSideNum; n++)
|
|
{
|
|
TGGeRegionSide &wl = *(*aSide.g_pCurRegion)[n];
|
|
if (wl.GetCurSide())
|
|
{
|
|
wl.SetRightRegion(aSide.g_pCurRegion);
|
|
}
|
|
else
|
|
{
|
|
wl.SetLeftRegion(aSide.g_pCurRegion);
|
|
}
|
|
}
|
|
|
|
return RTNORM;
|
|
}
|
|
|
|
//移除重合的区域,返回移除的数目
|
|
int TSearchRegionFromCurve::RemoveDupRegions()
|
|
{
|
|
int nRemoveNum = 0;
|
|
TDPtrList<TGGeRegion> ®ions = m_regions;
|
|
int nRegionNum = regions.Length();
|
|
|
|
for (int i = 0; i < nRegionNum; i++)
|
|
{
|
|
TGGeRegion ®Src = *regions[i];
|
|
BOOL bFindRev = FALSE;
|
|
for (int j = i+1; j < nRegionNum; j++)
|
|
{
|
|
TGGeRegion ®Dest = *regions[j];
|
|
if (regDest.IsEqualTo(regSrc))
|
|
{
|
|
regions.Remove();
|
|
nRemoveNum++;
|
|
bFindRev = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bFindRev)
|
|
{
|
|
nRegionNum--;
|
|
}
|
|
}
|
|
|
|
return nRemoveNum;
|
|
}
|
|
|
|
// 从初始组中移邻接的区域到当前组, 返回移动的数目
|
|
int TSearchRegionFromCurve::AddAdjacentRegion(TDPtrList<int> &curGroup, TDPtrList<int> &initGroup) const
|
|
{
|
|
int nInitNum = initGroup.Length();
|
|
if (!nInitNum)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
curGroup.Reset();
|
|
curGroup.Append(new int(*initGroup[0]));
|
|
initGroup.Remove(); //移除当前
|
|
nInitNum--;
|
|
|
|
BOOL bRepeat = FALSE; //发生组移动时,设置标记
|
|
do
|
|
{
|
|
bRepeat = FALSE;
|
|
for (int n = 0; n < nInitNum; n++)
|
|
{
|
|
int &idxRegion = *initGroup[n];
|
|
const TGGeRegion ®ion = m_regions[idxRegion];
|
|
BOOL bFind = FALSE;
|
|
for (int i = 0; i < curGroup.Length(); i++)
|
|
{
|
|
int &idxRegion1 = *curGroup[i];
|
|
ASSERT(idxRegion != idxRegion1);
|
|
if (region.IsAdjacentTo(m_regions[idxRegion1]))
|
|
{
|
|
bFind = TRUE;
|
|
curGroup.Append(new int(idxRegion));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bFind)
|
|
{
|
|
nInitNum--;
|
|
n--;
|
|
initGroup.Remove();
|
|
bRepeat = TRUE;
|
|
}
|
|
}
|
|
} while(bRepeat);
|
|
|
|
return curGroup.Length();
|
|
}
|
|
|
|
//求最外区域, 返回数目
|
|
int TSearchRegionFromCurve::GetOutsideRegions(TDPtrList<int> &lstOutIndex) const
|
|
{
|
|
TDPtrList<int> initGroup;
|
|
int nRegionNum = m_regions.Length();
|
|
for (int i = 0; i < nRegionNum; i++)
|
|
{
|
|
initGroup.Append(new int(i));
|
|
}
|
|
|
|
if (!nRegionNum)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
TDPtrList<int> newGroup;
|
|
if (g_bEchoSearch)
|
|
{
|
|
acedSetStatusBarProgressMeter(_T("判断区域边界"), 0, nRegionNum);
|
|
}
|
|
|
|
int nPos = 0;
|
|
do
|
|
{
|
|
if (!!newGroup)//完成一组的划分
|
|
{
|
|
int idx = *newGroup[0];
|
|
double dArea = fabs(m_regions[idx].PathArea());
|
|
for (int n = 1; n < newGroup.Length(); n++)
|
|
{
|
|
int idx1 = *newGroup[n];
|
|
double dArea1 = fabs(m_regions[idx1].PathArea());
|
|
if (dArea1 > dArea)
|
|
{
|
|
dArea = dArea1;
|
|
idx = idx1;
|
|
}
|
|
}
|
|
|
|
lstOutIndex.Append(new int(idx));
|
|
|
|
if (g_bEchoSearch)
|
|
{
|
|
nPos += newGroup.Length();
|
|
acedSetStatusBarProgressMeterPos(nPos);
|
|
}
|
|
}
|
|
} while(AddAdjacentRegion(newGroup, initGroup));
|
|
|
|
if (g_bEchoSearch)
|
|
{
|
|
acedRestoreStatusBar();
|
|
}
|
|
|
|
return lstOutIndex.Length();
|
|
}
|
|
|
|
int TSearchRegionFromCurve::ComparePointBySortXY(const TADSGePoint3d *p1, const TADSGePoint3d *p2)
|
|
{
|
|
double xDist = (p1->x - p2->x);
|
|
if (xDist < -_DIST_SNAP)
|
|
{
|
|
return -1;
|
|
}
|
|
else if (xDist > _DIST_SNAP)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
double yDist = (p1->y - p2->y);
|
|
if (yDist < -_DIST_SNAP)
|
|
{
|
|
return -1;
|
|
}
|
|
else if (yDist > _DIST_SNAP)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
} |