Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

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 &reg = 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> &regions = m_regions;
int nRegionNum = regions.Length();
for (int i = 0; i < nRegionNum; i++)
{
TGGeRegion &regSrc = *regions[i];
BOOL bFindRev = FALSE;
for (int j = i+1; j < nRegionNum; j++)
{
TGGeRegion &regDest = *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 &region = 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;
}