Files
envi-code/SourceCode/Code2026/tg_shs/shs_kernal/TSearchSpaceFromWall.cpp
T
2026-09-28 15:28:50 +08:00

1390 lines
33 KiB
C++
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//-------------------------------------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : TSearchSpaceFromWall 类
// = Version : ver2.0
// = Author : wlw
// = CreateDate : 2002-09-09
// = Description: TSearchSpaceFromWall 定义
// = Maintainers:
//
//-------------------------------------------------------------------------------------------------------+
#include "StdAfx.h"
#include "Symdef.h"
#include "TSearchSpaceFromWall.h"
#include "TAecSpaceWall.h"
#include "TAecSpaceCell.h"
#include "TDbWall.h"
#include "TGGiWallVector.h"
#include "TDbColumn.h"
#include "TAcDbObjectPtr.h"
#include "TArchCmdReactor.h"
#include "TGGeCurveSegment.h"
#include "TSortSideOnVertex.h"
#include "TADSGePoint3d.h"
#include "TSortWallOnPt.h"
#include "tgkatana.h"
void ErrorPosition(const TADSGePoint3d &, const TADSGePoint3d &, const TCHAR *);
TDPtrList<TSortWallOnPt> TSearchSpaceFromWall::g_lstAllSortWalls;
char TSearchSpaceFromWall::s_chConstructed = 0;
extern int g_nRunMode;
static int CmpSortWallLoc(const TSortWallOnPt *p1, const void *p2)
{
TSortWallOnPt *pp1=(TSortWallOnPt *)p1;
return !pp1->ExactInclude(*(const TADSGePoint3d *)p2);
}
static int ComparePoint2d(const TADSGePoint3d *p1, const void * p2)
{
TADSGePoint3d pt1 = *p1,
pt2 = *(const TADSGePoint3d *)p2;
BOOL bEqual = (fabs(pt1.x - pt2.x) <= _AS_SYS_UNIT(g_nDistPrec)
&& fabs(pt1.y - pt2.y) <= _AS_SYS_UNIT(g_nDistPrec));
return !bEqual;
}
static int ComparePoint2dByInclude(const TADSGePoint3d *p1, const void *p2)
{
TSortWallOnPt *pSortOnWall = (TSortWallOnPt *)p2;
return !pSortOnWall->ExactInclude(*p1);
}
TSearchSpaceFromWall::TSearchSpaceFromWall()
{
_SearchSpaceFromWall();
}
void TSearchSpaceFromWall::_SearchSpaceFromWall()
{
assert(!s_chConstructed);
s_chConstructed = 1;
TAecSpaceWall::g_pAllWalls = &walls;
TAecSpaceCell::g_pAllSpaces = &spaces;
TAecSpaceCell::g_nGlobalIndex = 0;
g_lstAllSortWalls.Reset();
}
// 支持后台数据库的搜索
void TSearchSpaceFromWall::InitStart(const TDPtrList<AcDbObjectId> &idWalls, const TDPtrList<AcDbObjectId> &idColus)
{
int nCount = idColus.Length();
for (int n = 0; n < nCount; n++)
{
TGGePoly2D polySrc(1);
const AcDbObjectId &idColu = idColus[n];
OPENOBJ_BEGIN(idColu, AcDb::kForRead, TDbColumn, pColu);
if (!pColu || pColu->IsFortifyColumn())
{
continue;
}
// sg modify 100728,根据8.5需求,搜索房间要考虑柱子保温
// pColu->GetOutline(polySrc);
pColu->GetColSurFacePoly2D(polySrc);
OPENOBJ_END();
TADSGePoint3d ptCen;
polySrc.Center(ptCen);
if (g_lstAllSortWalls.FindNode(ptCen, CmpSortWallLoc))
{
TchGeLib::adsout << _T("\n发现重合的柱子, 注意消除!");
}
else
{
TSortWallOnPt *pNode = new TSortWallOnPt(ptCen, idColu);
g_lstAllSortWalls.Append(pNode);
}
}
// 构造排序墙
int nLen = idWalls.Length();
for (int i = 0; i < nLen; i++)
{
TEntitySet ent;
AcDbObjectId id = idWalls[i];
if (acdbGetAdsName(ent.name, id) != Acad::eOk)
{
continue;
}
if (ent.Is(_T("CIRCLE")))
{
continue;
}
TAecSpaceWall *pWall = new TAecSpaceWall(ent);
if (!*pWall)
{
delete pWall;
continue;
}
else
{
NewAppend(pWall);
}
}
}
// 由选择集构造墙表
// ssWalls可以是Line也可以是AecWall
void TSearchSpaceFromWall::InitStart(TPickEntSet &ssWalls, const TDPtrList<AcDbObjectId> &lstColu)
{
int nFoundAt = 0;
int nCount = lstColu.Length();
for (int n = 0; n < nCount; n++)
{
TGGePoly2D polySrc(1);
const AcDbObjectId &idColu = lstColu[n];
OPENOBJ_BEGIN(idColu, AcDb::kForRead, TDbColumn, pColu);
if (!pColu || pColu->IsFortifyColumn())
{
continue;
}
// sg modify 100728,根据8.5需求,搜索房间要考虑柱子保温
// pColu->GetOutline(polySrc);
pColu->GetColSurFacePoly2D(polySrc);
OPENOBJ_END();
TADSGePoint3d ptCen;
polySrc.Center(ptCen);
if (g_lstAllSortWalls.FindNode(ptCen, CmpSortWallLoc))
{
extern GEOAPI BOOL g_bAutoCheckWall;
TADSGePoint3d ptLow, ptUp;
polySrc.GetExtend(ptLow, ptUp);
if (g_bAutoCheckWall)
{
TchGeLib::adsout << _T("\n发现重合的柱子, 注意消除!");
ErrorPosition(ptLow, ptUp, _T("重合的柱子"));
}
}
else
{
TSortWallOnPt *pNode = new TSortWallOnPt(ptCen, idColu);
g_lstAllSortWalls.Append(pNode);
}
}
// 构造排序墙
AcDbObjectId idWall;
long nLen = ssWalls.Length();
for (long i = 0; i < nLen; i++)
{
TEntitySet ent = ssWalls[i];
if (ent.Is(_T("CIRCLE")))
{
continue;
}
TAecSpaceWall *pWall = new TAecSpaceWall(ent);
if (!*pWall)
{
delete pWall;
continue;
}
else
{
NewAppend(pWall);
}
}
}
// 释放全局变量
TSearchSpaceFromWall::~TSearchSpaceFromWall()
{
TAecSpaceWall::g_pAllWalls = NULL;
TAecSpaceCell::g_pAllSpaces = NULL;
TAecSpaceCell::g_nGlobalIndex = 0;
g_lstAllSortWalls.Reset();
s_chConstructed = 0;
}
// 找墙体的两个节点,返回节点数目
int TSearchSpaceFromWall::FindLinkNode(const TAecSpaceWall *pWall, int *pIndex1, int *pIndex2)
{
int nNodeNum = 0;
for (int i = 0; i < g_lstAllSortWalls.Length(); i++)
{
TSortWallOnPt &wallsAtPos = *g_lstAllSortWalls[i];
TGGiWallVector *pVector = wallsAtPos.FindNode(&pWall->m_ent, TGGiWallVector::FindByEntity);
if (pVector)
{
nNodeNum++;
if (nNodeNum == 1)
{
*pIndex1 = i;
}
else
{
*pIndex2 = i;
}
if (nNodeNum >= 2)
{
break;
}
}
}
return nNodeNum;
}
// 更新柱子的连接信息
void TSearchSpaceFromWall::UpdateColuLinkage(const TGGeRectAngle *box)
{
for (int i = 0; i < g_lstAllSortWalls.Length(); i++)
{
TSortWallOnPt &wallsAtPos = *g_lstAllSortWalls[i];
if (!wallsAtPos.m_idColumn)
{
continue;
}
wallsAtPos.UpdateColuLinkage(box);
}
}
// 在墙角打断墙体
void TSearchSpaceFromWall::BreakWalls(TADSGePointList &lstCorners, TPickEntSet &ssAdd)
{
int nLen = g_lstAllSortWalls.Length();
/*-------------------------------------------------------------------------------
//错误说明:
//解决方法:
// BreakWallAt 函数内部对 walls 重复的提取外部边界耗费大量的时间,导致系统变慢
// 所以本类增加 m_mapWallId2OutlinePl 缓冲属性,在获取wall 的外部边界时,通过id
// 临时保存wall的边界,使得取边界一次即可,节约了整体时间
//修改人: lfy
//日期 : 2010-4-28
---------------------------------------------------------------------------------*/
long lKey = 0l;
PVOID pVal = NULL;
TGGePoly2D* pPl = NULL;
for (POSITION ps = m_mapWallId2OutlinePl.GetStartPosition();ps != NULL;)
{
pVal = NULL;
m_mapWallId2OutlinePl.GetNextAssoc(ps,lKey,pVal);
if (pVal != NULL)
{
pPl = (TGGePoly2D*)pVal;
delete pPl;
}
}
m_mapWallId2OutlinePl.RemoveAll();
for (int i = 0; i < nLen; i++)
{
BreakWallAt(i, lstCorners, ssAdd);
}
/*-------------------------------------------------------------------------------
//错误说明:
//解决方法:
// BreakWallAt 函数内部对 walls 重复的提取外部边界耗费大量的时间,导致系统变慢
// 所以本类增加 m_mapWallId2OutlinePl 缓冲属性,在获取wall 的外部边界时,通过id
// 临时保存wall的边界,使得取边界一次即可,节约了整体时间
//修改人: lfy
//日期 : 2010-4-28
---------------------------------------------------------------------------------*/
for (ps = m_mapWallId2OutlinePl.GetStartPosition();ps != NULL;)
{
pVal = NULL;
m_mapWallId2OutlinePl.GetNextAssoc(ps,lKey,pVal);
if (pVal != NULL)
{
pPl = (TGGePoly2D*)pVal;
delete pPl;
}
}
m_mapWallId2OutlinePl.RemoveAll();
}
// 在第nPos个墙角断开墙段
// lstCorners -- 发生变化的墙角
// 返回: kTrue--合并进行; kFalse--没有合并
// Status: 考虑了墙体的底标高, 用区域来判断两端点是否相等
// 没有考虑在柱子处断开
Adesk::Boolean TSearchSpaceFromWall::BreakWallAt(int nPos, TADSGePointList &lstCorners, TPickEntSet &ssAdd)
{
TSortWallOnPt &wallsAtPos = *g_lstAllSortWalls[nPos];
// 是否在变化墙角
if (!lstCorners.FindNode(&wallsAtPos, ComparePoint2dByInclude))
{
return Adesk::kFalse;
}
TAecSpaceWall *pThisWall = NULL;
TDbWall *pDbWall1 = NULL;
AcDbObjectId idNewWall;
// add by xlc on 110106
Adesk::Boolean bRet = Adesk::kFalse;
for (int i = 0; i < walls.Length(); i++)
{
pThisWall = walls[i];
if (!pThisWall->m_pStartNode || !pThisWall->m_pEndNode)
{
TchGeLib::adsout << _T("\n严重警告: 墙体的位置关系发生错乱! ");
throw pThisWall;
continue;
}
ASSERT(!!pThisWall->m_ent);
TAcDbObjectPtr obj1(pThisWall->m_ent, AcDb::kForRead);
if (!obj1)
{
continue;
}
pDbWall1 = TDbWall::cast(obj1.m_pObject);
ASSERT(pDbWall1);
// Update New: 加入判据, 避免当墙的端点位于柱子内部时, 进行打断产生无效短墙
// 假如有柱子的话,ptLoc位于墙体内是断开; 否则ptLoc距离墙基线<g_nDistPrec时断开
if (pDbWall1->BreakAt(wallsAtPos.ptLoc, idNewWall, wallsAtPos.HasColumn() ? &wallsAtPos.polyExtend : NULL,&m_mapWallId2OutlinePl) == Adesk::kTrue)
{
ASSERT(!!idNewWall);
TEntitySet entNewWall;
acdbGetAdsName(entNewWall.name, idNewWall);
ssAdd += entNewWall; // Z add on 2003/11/14
TAecSpaceWall *pNewWall = new TAecSpaceWall(entNewWall);
walls.Append(pNewWall);
(TWallData &)(*pThisWall) = (TWallData &)(*pDbWall1); //修改数据
ASSERT(pThisWall->m_pStartNode && pThisWall->m_pEndNode);
TSortWallOnPt &wallsAtOne = *pThisWall->m_pStartNode,
&wallsAtTwo = *pThisWall->m_pEndNode;
if ( wallsAtOne.ExactInclude(pThisWall->StartPoint())
|| wallsAtOne.ExactInclude(pThisWall->EndPoint()))
{
TGGiWallVector *pVector = wallsAtTwo.FindNode(&pThisWall->m_ent, TGGiWallVector::FindByEntity);
ASSERT(pVector && pVector->pWall == pThisWall);
pVector->pWall = pNewWall;
if(wallsAtTwo.ExactInclude(pNewWall->StartPoint()))
{
pNewWall->m_pStartNode = &wallsAtTwo;
}
else
{
pNewWall->m_pEndNode = &wallsAtTwo;
}
}
else
{
TGGiWallVector *pVector = wallsAtOne.FindNode(&pThisWall->m_ent, TGGiWallVector::FindByEntity);
ASSERT(pVector && pVector->pWall == pThisWall);
pVector->pWall = pNewWall;
if (wallsAtOne.ExactInclude(pNewWall->StartPoint()))
{
pNewWall->m_pStartNode = &wallsAtOne;
}
else
{
pNewWall->m_pEndNode = &wallsAtOne;
}
}
//调整节点数据
//本节点,加入两段墙
obj1.Close(); //下列语句可能导致同用户的交互,因此必须关闭已经打开的对象
wallsAtPos.Insert(pNewWall);
wallsAtPos.Insert(pThisWall);
//modify by xlc on 110106 解决墙角插圆柱时墙角缺口的问题
//return Adesk::kTrue;
bRet = Adesk::kTrue;
}
}
//return Adesk::kFalse;
return bRet;
}
// 合并所有墙段
void TSearchSpaceFromWall::MergeWalls(TADSGePointList &lstCorners, TPickEntSet &ssDel)
{
int nLen = g_lstAllSortWalls.Length();
for (int i = 0; i < nLen; i++)
{
if (MergeWallAt(i, lstCorners, ssDel) == Adesk::kTrue)
{
i--;
nLen--;
}
}
}
namespace
{
void ProcessKatanaRelation(TAecSpaceWall *pKeep, TAecSpaceWall *pDel,
TDbWall *pKeepWall, TDbWall *pDelWall)
{
// 判断两墙左右
TAecSpaceWall *pLeft(NULL), *pRight(NULL);
if (pKeepWall->StartPoint() == pDelWall->EndPoint())
{
pRight = pKeep;
pLeft = pDel;
}
if (pKeepWall->EndPoint() == pDelWall->StartPoint())
{
pRight = pDel;
pLeft = pKeep;
}
// end
if (!pLeft || !pRight) return;
if (pLeft == pDel)
{
/*
DelWall KeepWall
|-----------|------------|--------------|------------|
|--OldLeft--|----Left----|-----Right----|--OldRight--|
|-----------|------------|--------------|------------|
|
被删除的刀对象
*/
// 将 keepwall 与 oldleft 关联
AcDbObjectId BegKatanaId = KatanaToolkit::GetBegKatanaIdByWall(pDelWall);
KatanaToolkit::SetBegKatanaIdForWall(pKeep, BegKatanaId);
KatanaToolkit::SetRightWallIdForKatana(pKeepWall->objectId(), BegKatanaId);
KatanaToolkit::SetBegKatanaIdForWall(pDelWall, AcDbObjectId::kNull);
// 修改反应器
AcDbObjectId LeftWallId = KatanaToolkit::GetLeftWallIdByKatana(BegKatanaId);
KatanaToolkit::UnRegister(pDelWall, LeftWallId);
KatanaToolkit::Register(pKeepWall, LeftWallId);
}
else if (pRight = pDel)
{
/*
KeepWall DelWall
|-----------|------------|--------------|------------|
|--OldLeft--|----Left----|-----Right----|--OldRight--|
|-----------|------------|--------------|------------|
|
被删除的刀对象
*/
// 将 keepwall 与 oldleft 关联
AcDbObjectId EndKatanaId = KatanaToolkit::GetEndKatanaIdByWall(pDelWall);
KatanaToolkit::SetEndKatanaIdForWall(pKeep, EndKatanaId);
KatanaToolkit::SetLeftWallIdForKatana(pKeepWall->objectId(), EndKatanaId);
KatanaToolkit::SetEndKatanaIdForWall(pDelWall, AcDbObjectId::kNull);
// 修改反应器
AcDbObjectId RightWallId = KatanaToolkit::GetRightWallIdByKatana( EndKatanaId);
KatanaToolkit::UnRegister(pDelWall, RightWallId);
KatanaToolkit::Register(pKeepWall, RightWallId);
}
}
}
// 在第nPos个墙角合并墙段
// lstCorners -- 发生变化的墙角
// 返回: kTrue--合并进行; kFalse--没有合并
// Status: 考虑了墙体的底标高
Adesk::Boolean TSearchSpaceFromWall::MergeWallAt(int nPos, TADSGePointList &lstCorners, TPickEntSet &ssDel)
{
TSortWallOnPt &wallsAtPos = *g_lstAllSortWalls[nPos];
if (wallsAtPos.Length() != 2 || wallsAtPos.HasColumn())
{
return Adesk::kFalse;
}
int nTotalWalls = walls.Length();
TADSGePoint3d ptToBeMerged = wallsAtPos.ptLoc;
for(int i = 0; i < nTotalWalls; i++)
{
TWallData &wall = *walls[i];
ptToBeMerged.z = wall.GetElevation();
//在某墙段内不能合并
if ((ptToBeMerged&wall) == PR_INSIDE)
{
return Adesk::kFalse;
}
}
// 是否在变化墙角
int nCornerPos = -1;
//没有柱子的时候可以用点相等来比较
if (lstCorners.FindNode(&wallsAtPos.ptLoc, ComparePoint2d))
{
nCornerPos = lstCorners.CurPosition();
}
else
{
return Adesk::kFalse;
}
TGGiWallVector &vt1 = *wallsAtPos[0], &vt2 = *wallsAtPos[1]; //vt2的墙被合到vt1
ASSERT(!!vt1.pWall->m_ent && !!vt2.pWall->m_ent);
double dFistWallLenght = vt1.pWall->GetLength();
if (vt1.pWall->MergeWith(*vt2.pWall))
{
TAcDbObjectPtr obj1(vt1.pWall->m_ent, AcDb::kForWrite),
obj2(vt2.pWall->m_ent, AcDb::kForWrite);
if (!obj1 || !obj2)
{
return Adesk::kFalse;
}
TDbWall *pDbWall1 = TDbWall::cast(obj1.m_pObject);
TDbWall *pDbWall2 = TDbWall::cast(obj2.m_pObject);
ASSERT(pDbWall1 && pDbWall2);
// 处理 katana 对象关系 by gjm
// 由于 vt1.pWall 会覆盖掉 pDBWall1, 而 vt1.pWall内信息又不全,故这里放入所有参数.
ProcessKatanaRelation(vt1.pWall, vt2.pWall, pDbWall1, pDbWall2);
//modify by xlc on 101027 解决墙体合并后更新不及时的问题
ModifyModelRecordZone(pDbWall1);
ModifyModelRecordZone(pDbWall2);
pDbWall1->assertWriteEnabled();
(TWallData &)(*pDbWall1 ) = *vt1.pWall;
//add by xlc on 120509 提前对带形窗处理,解决墙体合并时带形窗丢失的问题
int k=0;
for (k = 0; k < pDbWall2->GetOpeningIdList().Length(); k++)
{
AcDbSoftPointerId id = pDbWall2->GetOpeningIdList()[k];
OPENOBJ_BEGIN(id, AcDb::kForWrite, TDbBandWin, pEnt);
if (pEnt)
{
if (pEnt->FindWallId(pDbWall1->objectId()) == NOT_FOUND)
{
pEnt->ModifyWallId(pDbWall2->objectId(), pDbWall1->objectId());
}
pDbWall2->RemoveReferenceOpening(id);
pDbWall1->AddOpeningId(id);
}
OPENOBJ_END();
}
// 合并墙体,调整门窗对墙体的引用
pDbWall2->MoveOpeningTo(*pDbWall1);
pDbWall2->MovePatchTo(*pDbWall1);
TAecSpaceWall &wall1 = *vt1.pWall,
&wall2 = *vt2.pWall;
TSortWallOnPt *pNode2 = wall2.m_pStartNode == &wallsAtPos
? wall2.m_pEndNode : wall2.m_pStartNode;
if (wall1.m_pStartNode == &wallsAtPos)
{
wall1.m_pStartNode = pNode2;
}
else
{
wall1.m_pEndNode = pNode2;
}
TGGiWallVector *pVector = pNode2->FindNode(&wall2.m_ent, TGGiWallVector::FindByEntity);
ASSERT(pVector && pVector->pWall == &wall2);
pVector->pWall = &wall1;
acedSSSetFirst(NULL,NULL); //add by wlw on 20160914 CAD2015以上平台,解决墙体融合崩溃
//删除另一墙段
ssDel += pDbWall2->objectId();
pDbWall2->erase();
TDbCurtainWall::RearrangeCol(pDbWall1, dFistWallLenght);
obj2.Close();
obj1.Close();
for (int i = 0; i < walls.Length(); i++)
{
if (walls[i] == &wall2)
{
walls.Remove();
break;
}
}
//消除本节点
g_lstAllSortWalls.Remove(nPos);
lstCorners.Remove(nCornerPos); //减变化墙角
return Adesk::kTrue;
}
return Adesk::kFalse;
}
// 在全局墙表中添加一项并根据需要构造排序墙表
// Status: 考虑了墙体的底标高
void TSearchSpaceFromWall::NewAppend(TAecSpaceWall *pWall)
{
walls.Append(pWall);
for(int n = 0; n < 2; n++)
{
TSortWallOnPt *pSortWall1 = g_lstAllSortWalls.FindNode(n ? &pWall->EndPoint() : &pWall->StartPoint(), CmpSortWallLoc);
if (pSortWall1)
{
pSortWall1->Insert(pWall);
}
else
{
pSortWall1 = new TSortWallOnPt(n ? pWall->GetEndPoint() : pWall->GetStartPoint(), AcDbObjectId::kNull);
pSortWall1->Insert(pWall);
g_lstAllSortWalls.Append(pSortWall1);
}
}
}
// 由AecSpaceWall生成AecWall实体
// bCreateAlone是否创建孤独的不连接两个空间的墙, 在轴线变墙时用到
void TSearchSpaceFromWall::CreateWalls(BOOL bCreateAlone)
{
BOOL bOldVar = g_bDwgBegin;
DocSetIsDwgBegin(FALSE); //加速
TDPtrList<TGGeCurveSegment> lstCurves;
int nLen=walls.Length();
for (int i = 0; i < nLen; i++)
{
TAecSpaceWall &wall = *walls[i];
if (!bCreateAlone && !wall.leftSpace && !wall.rightSpace)
{
continue;
}
// v2.0 求墙体参数不在这儿
if (g_nRunMode)
{
TGGeCurveSegment *lCurve = new TGGeCurveSegment;
TGGeCurveSegment *rCurve = new TGGeCurveSegment;
wall.CalSideParameters(wall.m_ent, g_lstAllSortWalls, *lCurve, *rCurve);
if (!(*lCurve))
{
delete lCurve;
}
else
{
lstCurves.Append(lCurve);
}
if (!(*rCurve))
{
delete rCurve;
}
else
{
lstCurves.Append(rCurve);
}
}
else
{
TDbWall *pWall = new TDbWall;
pWall->SetLayerHatch2d(InitLayer(LAY_HATCH, FALSE));//add by W on 050531
TWallData &wall1 = *pWall;
wall1 = wall;
pWall->AddToMSpace(Adesk::kTrue);
acdbGetAdsName(wall.m_ent.name,pWall->objectId()); //把单线的实体名换成墙实体名
}
}
if (g_nRunMode)
{
RemoveDupCurves(lstCurves);
nLen = lstCurves.Length();
for (i = 0; i < nLen; i++)
{
lstCurves[i]->Make(LAY_WALL);
}
}
else
{
for (i = 0; i < nLen; i++)
{
TEntitySet &ent = walls[i]->m_ent;
OPENOBJ_BEGIN(ent, AcDb::kForWrite, TDbWall, pWall);
if (pWall)
{
pWall->assertWriteEnabled();
pWall->CalSideParameters(ent, TSearchSpaceFromWall::g_lstAllSortWalls);
}
OPENOBJ_END();
}
for (i = 0; i < nLen; i++)
{
TEntitySet &ent = walls[i]->m_ent;
OPENOBJ_BEGIN(ent, AcDb::kForWrite, TDbWall, pWall);
if (pWall)
{
pWall->assertWriteEnabled();
pWall->CalSideParameters1();
}
OPENOBJ_END();
}
//wlw 2014.05.20 下面代码更新柱子会全图更新,并影响柱子和墙的融合先注释掉,如果对其它功能有影响请提出
//UpdateColuLinkage();
}
TArchCmdReactor::ResetAll();
DocSetIsDwgBegin(bOldVar);
}
// 通过一实体名找墙体
TAecSpaceWall * TSearchSpaceFromWall::FindWall(const TEntitySet &ent)
{
for (int i = 0; i < walls.Length(); i++)
{
TAecSpaceWall *pWall = walls[i];
if (pWall->m_ent == ent)
{
return pWall;
}
}
return NULL;
}
//取得在墙角的所有实体
//Status: 考虑了不同标高
void TSearchSpaceFromWall::GetEntitiesAtCorners(TADSGePointList &lstCorners, TPickEntSet &ss)
{
int nNum = g_lstAllSortWalls.Length();
for (int n = 0; n < nNum; n++)
{
TSortWallOnPt *pSortWallAtCorner = g_lstAllSortWalls[n];
int nCount = lstCorners.Length();
for (int i = 0; i < nCount; i++)
{
TADSGePoint3d ptCorner = *lstCorners[i];
if (pSortWallAtCorner->ExactInclude(ptCorner))
{
for (int j = 0; j < pSortWallAtCorner->Length(); j++)
{
ss += (*pSortWallAtCorner)[j]->pWall->m_ent;
}
}
}
}
}
// 取得所有的墙角
// 参数: lstCorners(OUT)--获得的墙角
void TSearchSpaceFromWall::GetAllCorners(TADSGePointList &lstCorners)
{
int nNum = g_lstAllSortWalls.Length();
for (int n = 0; n < nNum; n++)
{
TSortWallOnPt *pSortWallAtCorner = g_lstAllSortWalls[n];
lstCorners.Append(new TADSGePoint3d(pSortWallAtCorner->ptLoc));
}
}
// 功能: 找所有的空间
// 并设置外墙标志
// 返回室外空间
TAecSpaceCell * TSearchSpaceFromWall::SearchSpaces()
{
TAecSpaceCell * ptrExt = SearchExtSpace(walls, spaces);
if (ptrExt)
{
int nWallNum = walls.Length();
for (int i = 0; i < nWallNum; i++)
{
TAecSpaceWall &wall = *walls[i];
if (wall.leftSpace == ptrExt)
{
wall.m_nWallFlag |= WF_EXTERNAL;
wall.m_nWallFlag |= WF_LEFTEXT;
}
else if (wall.rightSpace == ptrExt)
{
wall.m_nWallFlag |= WF_EXTERNAL;
wall.m_nWallFlag &= ~WF_LEFTEXT;
}
else
{
wall.m_nWallFlag &= ~WF_EXTERNAL;
wall.m_nWallFlag &= ~WF_LEFTEXT;
}
}
}
return ptrExt;
}
// 通过给定的点搜索房间
// 返回: 0--没有找到; 1--室内; 2--室外
int TSearchSpaceFromWall::SearchSpace(const TADSGePoint3d &ptPick, TAecSpaceCell &space)
{
int nRetFlag = 0;
int nWallNumber = walls.Length();
// 查找最近墙
TAecSpaceWall *pNearestWall = NULL;
ads_real nMinDist = 0.0;
for (int i = 0; i < nWallNumber; i++)
{
TADSGePoint3d ptProject;
TAecSpaceWall *pWall = walls[i];
if (pWall->ProjectToMe(ptPick, ptProject) != RTNORM || (ptProject&(*pWall)) != PR_INSIDE)
{
continue;
}
ptProject.z = ptPick.z; //忽略Z坐标
ads_real nDist = ads_distance(ptPick, ptProject);
if (!pNearestWall)
{
nMinDist = nDist;
pNearestWall = pWall;
}
else if (nDist < nMinDist)
{
nMinDist = nDist;
pNearestWall = pWall;
}
}
int nSide = 0; //1:left; 2:right
BOOL bSubtract = TRUE; //用相减的方法,适合于室内; 否则为室外
TAecSpaceCell lSpace, rSpace, *pSpace = NULL;
if (pNearestWall && SearchTwoSpace(*pNearestWall, lSpace, rSpace) == RTNORM)
{
TGGePoly2D lPoly, rPoly;
lSpace.CenterPoly2D(lPoly);
rSpace.CenterPoly2D(rPoly);
int nPrFlag1 = ptPick&lPoly;
int nPrFlag2 = ptPick&rPoly;
if (nPrFlag1 == PR_INSIDE && nPrFlag2 == PR_INSIDE)
{
//两个都包括该点, 则取面积较小的, 并且一定是室内空间
ads_real nArea1 = lPoly.Area();
ads_real nArea2 = rPoly.Area();
if (nArea1 < nArea2)
{
pSpace = &lSpace;
nSide = 1;
}
else
{
pSpace = &rSpace;
nSide = 2;
}
nRetFlag = 1;
}
else if (nPrFlag1 == PR_INSIDE)
{
pSpace = &lSpace;
nSide = 1;
nRetFlag = 1;
}
else if (nPrFlag2 == PR_INSIDE)
{
pSpace = &rSpace;
nSide = 2;
nRetFlag = 1;
}
else
{ // 双方都不包含给定的点, 那么一定是室外空间, 并且取面积较大的
ads_real nArea1 = lPoly.Area();
ads_real nArea2 = rPoly.Area();
if (nArea1 > nArea2)
{
pSpace = &lSpace;
nSide = 1;
}
else
{
pSpace = &rSpace;
nSide = 2;
}
nRetFlag = 2;
bSubtract= FALSE;
}
}
if (nRetFlag)
{
TAecSpaceCell &spFind = *pSpace;
space.Reset();
for (int n = 0; n < spFind.Length(); n++)
{
TAecSpaceWall *pWall = spFind[n];
if (pWall->leftSpace == pSpace)
{
pWall->leftSpace = &space;
}
else
{
pWall->rightSpace = pSpace;
}
space.Append(pWall);
}
}
return nRetFlag;
}
// 根据内外墙设置缺省宽度
// 备注: 事先得找出所有的房间,用SearchSpaces
void TSearchSpaceFromWall::SetDefaultWidth()
{
int nWallNum = walls.Length();
for (int i = 0; i < nWallNum; i++)
{
TAecSpaceWall &wall = *walls[i];
if (wall.m_nWallFlag & WF_EXTERNAL)
{
if (wall.m_nWallFlag & WF_LEFTEXT)
{
wall.m_lWidth = _AS_SYS_UNIT(g_nExtWidth);
wall.m_rWidth = _AS_SYS_UNIT(g_nIntWidth);
}
else
{
wall.m_lWidth = _AS_SYS_UNIT(g_nIntWidth);
wall.m_rWidth = _AS_SYS_UNIT(g_nExtWidth);
}
}
else
{
wall.m_lWidth = _AS_SYS_UNIT(g_nIntWallWidth) / 2.0;
wall.m_rWidth = _AS_SYS_UNIT(g_nIntWallWidth) / 2.0;
}
}
}
// 搜索一墙的左右房间
// 参数:
// aWall(IN)--给定的墙
// lSpace(OUT)--左边的空间
// rSpace(OUT)--右边的空间
// 返回: RTNORM/RTERROR
int TSearchSpaceFromWall::SearchTwoSpace(TAecSpaceWall &aWall,
TAecSpaceCell &lSpace, TAecSpaceCell &rSpace)
{
if (!aWall)
{
return RTERROR;
}
aWall.g_pCurSpace = aWall.leftSpace = &lSpace;
lSpace.Push(&aWall);
if (aWall.Trival(aWall.m_pStartNode, 0) != RTNORM)
{
return RTERROR;
}
int nWallNum = TAecSpaceWall::g_pCurSpace->Length();
for (int n = 0; n < nWallNum; n++)
{
TAecSpaceWall &wall = *(*aWall.g_pCurSpace)[n];
if (wall.curSide)
{
wall.rightSpace = aWall.g_pCurSpace;
}
else
{
wall.leftSpace = aWall.g_pCurSpace;
}
}
aWall.g_pCurSpace = aWall.rightSpace = &rSpace;
rSpace.Push(&aWall);
if (aWall.Trival(aWall.m_pStartNode, 1) != RTNORM)
{
return RTERROR;
}
nWallNum = TAecSpaceWall::g_pCurSpace->Length();
for (n = 0; n < nWallNum; n++)
{
TAecSpaceWall &wall = *(*aWall.g_pCurSpace)[n];
if (wall.curSide)
{
wall.rightSpace = aWall.g_pCurSpace;
}
else
{
wall.leftSpace = aWall.g_pCurSpace;
}
}
return RTNORM;
}
// 查找左侧或右侧房间
int TSearchSpaceFromWall::SearchOneSpace(TAecSpaceWall &aWall,
int nSide, TAecSpaceCell &aSpace)
{
if (!aWall)
{
return RTERROR;
}
if (nSide == 0)
{
aWall.g_pCurSpace = aWall.leftSpace = &aSpace;
aSpace.Push(&aWall);
if (aWall.Trival(aWall.m_pStartNode, 0) != RTNORM)
{
return RTERROR;
}
int nWallNum = TAecSpaceWall::g_pCurSpace->Length();
for (int n = 0; n < nWallNum; n++)
{
TAecSpaceWall &wall = *(*aWall.g_pCurSpace)[n];
if (wall.curSide)
{
wall.rightSpace = aWall.g_pCurSpace;
}
else
{
wall.leftSpace = aWall.g_pCurSpace;
}
}
}
else
{
aWall.g_pCurSpace = aWall.rightSpace = &aSpace;
aSpace.Push(&aWall);
if (aWall.Trival(aWall.m_pStartNode, 1) != RTNORM)
{
return RTERROR;
}
int nWallNum = TAecSpaceWall::g_pCurSpace->Length();
for (int n = 0; n < nWallNum; n++)
{
TAecSpaceWall &wall = *(*aWall.g_pCurSpace)[n];
if (wall.curSide)
{
wall.rightSpace = aWall.g_pCurSpace;
}
else
{
wall.leftSpace = aWall.g_pCurSpace;
}
}
}
return RTNORM;
}
// 找由fromWall到toWall的一条路径, 应当没有找出区域的情况下使用
int TSearchSpaceFromWall::SearchPath(TAecSpaceWall &fromWall, TAecSpaceWall &toWall, TDPtrStack<TAecSpaceWall> &lstWallPath)
{
if (!fromWall)
{
return 0;
}
TAecSpaceCell lSpace, rSpace;
fromWall.g_pCurSpace = fromWall.leftSpace = &lSpace;
lSpace.Push(&fromWall);
if (fromWall.TrivalTo(toWall, fromWall.m_pStartNode, 0) == RTNORM)
{ //按正向
int nWallNum = TAecSpaceWall::g_pCurSpace->Length();
for (int n = 0; n < nWallNum; n++)
{
TAecSpaceWall *wall = (*fromWall.g_pCurSpace)[n];
lstWallPath.Push(wall);
}
return 1;
}
fromWall.g_pCurSpace = fromWall.rightSpace = &rSpace;
rSpace.Push(&fromWall);
if (fromWall.TrivalTo(toWall, fromWall.m_pEndNode, 0) == RTNORM)
{ //按逆向
int nWallNum = TAecSpaceWall::g_pCurSpace->Length();
for (int n = 0; n < nWallNum; n++)
{
TAecSpaceWall *wall = (*fromWall.g_pCurSpace)[n];
lstWallPath.Push(wall);
}
return 2;
}
return 0;
}
int TSearchSpaceFromWall::SearchPath(TAecSpaceWall &fromWall, TAecSpaceWall &toWall, TGGePoly2D &poly, int nType)
{
TDPtrStack<TAecSpaceWall> lstWalls;
int nRetCode = SearchPath(fromWall, toWall, lstWalls);
if (!nRetCode)
{
return RTERROR;
}
poly.Reset();
poly.SetFlag(0);
int nLen = lstWalls.Length();
if (!nLen)
{
return RTERROR;
}
TAecSpaceWall &wall0 = *lstWalls[0];
TGGeCurveSegment wall = wall0;
if (nType == 1)
{
wall = wall0.GetStdOffsetCurveFromCenter(OFFSET_LEFT, 0.0);
}
else if (nType == 2)
{
wall = wall0.GetStandardSideCurve(OFFSET_LEFT,0,TRUE);
}
else if (nType == 3)
{
wall = wall0.GetStandardSideCurve(OFFSET_RIGHT,0,TRUE);
}
TDualPtrList<TSortWallOnPt*> lstNode;
if (nLen == 1 && wall.Is(CURVE_CIRCLE))// 分成两个半圆
{
ASSERT(0); //不考虑圆墙
}
else
{
TGGeCurveSegment cvLastSeg = wall;
cvLastSeg.SetLineFlag(LS_INFINITE);
TADSGePoint3d ptS = nRetCode == 1 ? wall.GetStartPoint() : wall.GetEndPoint();
for (int i = 0; i < nLen; i++)
{
TAecSpaceWall &curWall = *lstWalls[i];
lstNode.FindOrAddTail(curWall.m_pStartNode);
lstNode.FindOrAddTail(curWall.m_pEndNode);
if ( i > 0 && nType > 1)
{
if (curWall.m_pStartNode == lstWalls[i-1]->m_pStartNode
|| curWall.m_pEndNode== lstWalls[i-1]->m_pEndNode)//反一下
{
if (nType == 2)
{
nType = 3;
}
else if (nType == 3)
{
nType = 2;
}
}
}
TGGeCurveSegment curSeg = curWall;
if (nType == 1)
{
curSeg = curWall.GetStdOffsetCurveFromCenter(OFFSET_LEFT, 0.0);
}
else if (nType == 2)
{
curSeg = curWall.GetStandardSideCurve(OFFSET_LEFT,0,TRUE);
}
else if (nType == 3)
{
curSeg = curWall.GetStandardSideCurve(OFFSET_RIGHT,0,TRUE);
}
double *pNextPt = curSeg.FarPoint(ptS);
//modify by xlc on 100414解决阳台沿墙绘制时圆弧部分错误的问题
//if (pNextPt == &(curSeg.GetStartPoint().x) && curSeg.Is(CURVE_ARC))
if (pNextPt == &(curSeg.StartPoint().x) && curSeg.Is(CURVE_ARC))
{
poly.AppendNode(ptS, -curSeg.GetBulge());
}
else
{
poly.AppendNode(ptS, curSeg.GetBulge());
}
ptS = pNextPt;
}
poly.AppendNode(ptS);
}
// Modify on 2002/2/21 by Z 忽略Z坐标
poly.SetElevation(0.0);
return RTNORM;
}
// 更新墙体标志(内外墙)
void TSearchSpaceFromWall::UpdateWallFlags()
{
for (int i = 0; i < walls.Length(); i++)
{
TAecSpaceWall *pWall = walls[i];
ASSERT(!!pWall->m_ent);
TAcDbObjectPtr obj(pWall->m_ent, AcDb::kForWrite);
if (!obj)
{
continue;
}
TDbWall *pDbWall = TDbWall::cast(obj.m_pObject);
if (pDbWall)
{
pDbWall->assertWriteEnabled();
pDbWall->m_nWallFlag = pWall->m_nWallFlag;
}
}
}
// 搜出所有房间(包括室外空间), 并返最大室外空间
// 参数:
// walls(IN)--所有的墙
// spaces(OUT)--所有的空间
// Note: 仅限于内部使用
// modified by W 080103,解决室外空间确定个别情况误判问题
TAecSpaceCell * TSearchSpaceFromWall::SearchExtSpace(TDPtrList<TAecSpaceWall> &walls, TDPtrList<TAecSpaceCell> &spaces)
{
double dMinPathArea = 0;
TAecSpaceCell *extCell = NULL;
// 查找墙两侧的房间
int nLen = walls.Length();
for (int i = 0; i < nLen; i++)
{
TAecSpaceWall &aWall = *walls[(int)i];
TSortWallOnPt *pSortWalls = aWall.m_pStartNode;
if (!pSortWalls) // 当前墙孤立
{
continue;
}
if (!(nLen % 50))
{
TchGeLib::adsout << _T(".");
}
aWall.g_pCurSpace = NULL;
if (!aWall.leftSpace)
{
aWall.g_pCurSpace = new TAecSpaceCell;
aWall.g_pCurSpace->Push(&aWall);
if (aWall.Trival(aWall.m_pStartNode, 0) == RTNORM)
{
spaces.Append(aWall.g_pCurSpace);
int nWallNum = TAecSpaceWall::g_pCurSpace->Length();
for (int n = 0; n < nWallNum; n++)
{
TAecSpaceWall &wl = *(*aWall.g_pCurSpace)[n];
if (wl.curSide)
{
wl.rightSpace = aWall.g_pCurSpace;
}
else
{
wl.leftSpace = aWall.g_pCurSpace;
}
}
aWall.g_pCurSpace->Reverse(); // add by W 080103,保证内环顺时针
// sg add 091106,解决离坐标原点较远时,积分出错的情况
//double pathArea = aWall.g_pCurSpace->PathArea();
double dPathArea = aWall.g_pCurSpace->PathArea(pSortWalls->ptLoc);
if (dPathArea < dMinPathArea)
{
dMinPathArea = dPathArea;
extCell = aWall.g_pCurSpace;
}
aWall.g_pCurSpace->Reverse(); // 恢复方向
}
else
{
delete TAecSpaceWall::g_pCurSpace;
}
}
if (!aWall.rightSpace)
{
aWall.g_pCurSpace = new TAecSpaceCell;
aWall.g_pCurSpace->Push(&aWall);
if (aWall.Trival(aWall.m_pStartNode, 1) == RTNORM)
{
spaces.Append(aWall.g_pCurSpace);
int nWallNum = TAecSpaceWall::g_pCurSpace->Length();
for (int n = 0; n < nWallNum; n++)
{
TAecSpaceWall &wl = *(*aWall.g_pCurSpace)[n];
if (wl.curSide)
{
wl.rightSpace = aWall.g_pCurSpace;
}
else
{
wl.leftSpace = aWall.g_pCurSpace;
}
}
// sg add 091106,解决离坐标原点较远时,积分出错的情况
//double pathArea = aWall.g_pCurSpace->PathArea();
double dPathArea = aWall.g_pCurSpace->PathArea(pSortWalls->ptLoc);
if (dPathArea < dMinPathArea)
{
dMinPathArea = dPathArea;
extCell = aWall.g_pCurSpace;
}
}
else
{
delete TAecSpaceWall::g_pCurSpace;
}
}
}
return extCell;
}