//-------------------------------------------------------------------------------------------------------+ // 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 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 &idWalls, const TDPtrList &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 &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距离墙基线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 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 &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 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 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 &walls, TDPtrList &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; }