925 lines
24 KiB
C++
925 lines
24 KiB
C++
#include "StdAfx.h"
|
|
#include "TGKatana.h"
|
|
#include "TArchPerDocData.h"
|
|
#include "TArchDocReactor.h"
|
|
#include "TArchAppDocGlobals.h"
|
|
|
|
static std::vector<AcDbObjectId> g_deepCloneKatanas;
|
|
|
|
namespace
|
|
{
|
|
enum KAFLAG
|
|
{
|
|
eEndKatana = 0,
|
|
eBegKatana,
|
|
eLeftWall,
|
|
eRightWall,
|
|
};
|
|
// 判断两墙共线 true 共线
|
|
bool _JudgeCollinear(const TDbWall *pLeft, const TDbWall *pRight)
|
|
{
|
|
if (!pLeft || !pRight) return false;
|
|
if (pLeft->GetWidth() != pRight->GetWidth()) return false;
|
|
if (pLeft->GetMaterialIndex() != pRight->GetMaterialIndex()) return false;
|
|
if (pLeft->GetCurveType() != pRight->GetCurveType()) return false;
|
|
if (pLeft->EndPoint() != pRight->StartPoint()) return false;
|
|
if (pLeft->Is(CURVE_LINE))
|
|
{
|
|
TGGeCurveSegment seg = *pLeft;
|
|
seg.SetPoints(pLeft->StartPoint(), pRight->EndPoint());
|
|
double dist = seg.GetDist2Me(pLeft->EndPoint());
|
|
if (!EQUAL_ZERO(dist)) return false;
|
|
}
|
|
else if (pLeft->Is(CURVE_ARC))
|
|
{
|
|
// 上面算法,理论上可以兼容 直墙和弧墙,不过,TGGeCurveSegment 的 SetPoints()应该有BUG.
|
|
// 导致弧墙结果不正确. 现在用判断圆心法
|
|
TGGeArc arcLeft = pLeft->GetArc();
|
|
TGGeArc arcRight = pRight->GetArc();
|
|
if (arcLeft.GetCenterPt() != arcRight.GetCenterPt())
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 取曲线上的一点, offset 是 此点与 起点 或 终点 的距离. bstart 为真时, 是起点
|
|
AcGePoint3d _GetCurvePoint(TGGeCurveSegment &curve, bool bstart, double &offset )
|
|
{
|
|
TADSGePointDir2d res;
|
|
curve.Polar(offset, res, bstart ? 1 : 0);
|
|
return AcGePoint3d(res.x, res.y, res.z);
|
|
}
|
|
|
|
// 取实体外包框最 大/小 点 在 base 上的投影
|
|
void _GetEntLimtPtInBase(TDbEntity *pEnt, TGGeCurveSegment &base, TADSGePoint3d &ptLow, TADSGePoint3d &ptUP)
|
|
{
|
|
pEnt->GetExtents(ptLow, ptUP);
|
|
TDbOpening *pOpening = TDbOpening::cast(pEnt);
|
|
if (pOpening)
|
|
{
|
|
pOpening->GetSidePointsOnBase(ptUP, ptLow);
|
|
}
|
|
else
|
|
{
|
|
base.ProjectToMe(ptLow, ptLow);
|
|
base.ProjectToMe(ptUP, ptUP);
|
|
}
|
|
}
|
|
|
|
// 判断点是否在 门窗/pathc 上, 如果在,则返回离其最近的一点
|
|
// true - 在 门窗/patch 上
|
|
bool _JudgePtInOpeningAndPatch(TDbWall *pWall, const TADSGePoint3d &pt, TADSGePoint3d &ptNew)
|
|
{
|
|
TDPtrList<AcDbSoftPointerId>* plstO = const_cast< TDPtrList<AcDbSoftPointerId>* >(&(pWall->GetOpeningIdList()));
|
|
TDPtrList<AcDbSoftPointerId>* plstP = const_cast< TDPtrList<AcDbSoftPointerId>* >(&(pWall->GetPatchIdList()));
|
|
TDPtrList<AcDbSoftPointerId> lstO, lstP;
|
|
lstO.copyFrom(*plstO);
|
|
lstP.copyFrom(*plstP);
|
|
lstO << lstP;
|
|
TGGeCurveSegment seg(*pWall);
|
|
for (int i = 0; i < lstO.Length(); ++i)
|
|
{
|
|
OPENOBJ_BEGIN(*lstO[i], AcDb::kForWrite, TDbEntity, pO)
|
|
if (pO)
|
|
{
|
|
TADSGePoint3d pt1, pt2, ptMid;
|
|
_GetEntLimtPtInBase(pO, seg, pt1, pt2);
|
|
if (seg.PathDistance(pt1, 1) < seg.PathDistance(pt2, 1))
|
|
seg.SetPoints(pt1, pt2);
|
|
else
|
|
seg.SetPoints(pt2, pt1);
|
|
|
|
int flag = pt & seg;
|
|
if (flag == PR_INSIDE || flag == PR_ONPT1 || flag == PR_ONPT2) // 如果点在门窗内
|
|
{
|
|
if (seg.PathDistance(pt, 1) <= seg.PathDistance(pt, 0)) // 离起点近,返回起点
|
|
ptNew = seg.StartPoint();
|
|
else
|
|
ptNew = seg.EndPoint();
|
|
return true;
|
|
}
|
|
}
|
|
OPENOBJ_END()
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 将 pSrc 墙上 seg 曲线 上的 门窗 patch 实体,移动到 pDesc 墙上
|
|
// 算法不考虑seg的起/始点跨 门窗 patch 的情况.
|
|
void _ProcessOpeningAndPatch(TDbWall *pSrc, TDbWall *pDesc, TGGeCurveSegment &seg)
|
|
{
|
|
TDPtrList<AcDbSoftPointerId>* plstO = const_cast< TDPtrList<AcDbSoftPointerId>* >(&(pSrc->GetOpeningIdList()));
|
|
TDPtrList<AcDbSoftPointerId>* plstP = const_cast< TDPtrList<AcDbSoftPointerId>* >(&(pSrc->GetPatchIdList()));
|
|
TDPtrList<AcDbSoftPointerId> lstO, lstP;
|
|
lstO.copyFrom(*plstO);
|
|
lstP.copyFrom(*plstP);
|
|
lstO << lstP;
|
|
|
|
std::vector<AcDbObjectId> ids;
|
|
TGGeCurveSegment segTmp(seg);
|
|
for (int i = 0; i < lstO.Length(); ++i)
|
|
{
|
|
AcDbObjectId id = *lstO[i];
|
|
OPENOBJ_BEGIN(id, AcDb::kForWrite, TDbEntity, pO)
|
|
if (pO)
|
|
{
|
|
TADSGePoint3d pt1, pt2, ptMid;
|
|
_GetEntLimtPtInBase(pO, seg, pt1, pt2);
|
|
if (seg.PathDistance(pt1, 1) < seg.PathDistance(pt2, 1))
|
|
segTmp.SetPoints(pt1, pt2);
|
|
else
|
|
segTmp.SetPoints(pt2, pt1);
|
|
ptMid = segTmp.MidPoint();
|
|
if ((ptMid & seg) == PR_INSIDE) // 点在seg上,说明门窗也在
|
|
ids.push_back(id);
|
|
}
|
|
OPENOBJ_END()
|
|
}
|
|
AcDbEntity *pEnt(NULL);
|
|
for (size_t i = 0; i < ids.size(); ++i)
|
|
{
|
|
if (Acad::eOk == acdbOpenAcDbEntity(pEnt, ids[i], AcDb::kForRead))
|
|
{
|
|
if (pEnt->cast(TDbWallPatch::desc()))
|
|
{
|
|
pEnt->close();
|
|
pSrc->MoveOnePatchTo(*pDesc, ids[i]);
|
|
}
|
|
else
|
|
{
|
|
pEnt->close();
|
|
pSrc->MoveOneOpeningTo(*pDesc, ids[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 判断点否在墙外,如在墙外,则给出离墙距离 dOffset 的一点
|
|
// 如果点在墙内,但与 起/终 点距离小于 dOffset 也返回离墙距离 dOffset 的一点
|
|
// bLeft 是否是左墙
|
|
// true ptNew 有新值
|
|
bool _JudgePtInWall(TDbWall *pWall, const TADSGePoint3d &pt, TADSGePoint3d &ptNew, double &dOffset, bool bLeft)
|
|
{
|
|
TGGeCurveSegment segL, segR, seg;
|
|
pWall->GetSideCurve(segL, segR);
|
|
if (UPEQUAL_ZERO(segL.GetLength() - segR.GetLength())) // 取最短一条边,要求pt不能超过
|
|
seg = segR;
|
|
else
|
|
seg = segL;
|
|
TADSGePoint3d ptOn;
|
|
seg.ProjectToMe(pt, ptOn);
|
|
int flag = ptOn & seg;
|
|
if (flag != PR_INSIDE)
|
|
{
|
|
if (seg.PathDistance(ptOn, 1) < seg.PathDistance(ptOn, 0))
|
|
ptNew = _GetCurvePoint(seg, true, dOffset);
|
|
else
|
|
ptNew = _GetCurvePoint(seg, false, dOffset);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (bLeft && seg.PathDistance(ptOn, 1) < dOffset)
|
|
ptNew = _GetCurvePoint(seg, true, dOffset);
|
|
else if (!bLeft && seg.PathDistance(ptOn, 0) < dOffset)
|
|
ptNew = _GetCurvePoint(seg, false, dOffset);
|
|
else
|
|
return false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
AcDbObjectId _GetOtherWallId(TDbWall *pWall, bool bStart)
|
|
{
|
|
AcDbObjectId kaID = bStart ? pWall->GetStartKatanaID() : pWall->GetEndKatanaID();
|
|
OPENOBJ_BEGIN(kaID, AcDb::kForRead, CGlwKatana, pKa)
|
|
if (pKa)
|
|
{
|
|
if (pKa->GetLeftWallID() == pWall->objectId())
|
|
return pKa->GetRightWallID();
|
|
else if (pKa->GetRightWallID() == pWall->objectId())
|
|
return pKa->GetLeftWallID();
|
|
}
|
|
OPENOBJ_END()
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
void _UnRegisterReactor(/*CGlwKatana *pKa, */TDbWall *pLeft, TDbWall *pRight)
|
|
{
|
|
if (/*!pKa || */!pLeft || !pRight) return;
|
|
if (/*!pKa->isWriteEnabled() || */!pLeft->isWriteEnabled() || !pRight->isWriteEnabled()) return;
|
|
// pKa->removePersistentReactor(pLeft->objectId());
|
|
// pKa->removePersistentReactor(pRight->objectId());
|
|
pLeft->removePersistentReactor(pRight->objectId());
|
|
pRight->removePersistentReactor(pLeft->objectId());
|
|
}
|
|
|
|
void _UnRegisterReactor(CGlwKatana *pK)
|
|
{
|
|
if (pK && pK->isWriteEnabled())
|
|
{
|
|
OPENOBJ_BEGIN(pK->GetLeftWallID(), AcDb::kForWrite, TDbWall, pLeft)
|
|
OPENOBJ_BEGIN(pK->GetRightWallID(), AcDb::kForWrite, TDbWall, pRight)
|
|
if (pLeft && pRight)
|
|
_UnRegisterReactor(/*pK, */pLeft, pRight);
|
|
OPENOBJ_END()
|
|
OPENOBJ_END()
|
|
}
|
|
}
|
|
|
|
void _UnRegisterReactor(AcDbObjectId &kaID)
|
|
{
|
|
OPENOBJ_BEGIN(kaID, AcDb::kForWrite, CGlwKatana, pK)
|
|
if (pK)
|
|
_UnRegisterReactor(pK);
|
|
OPENOBJ_END()
|
|
}
|
|
|
|
void _RegisterReactor(/*CGlwKatana *pKa, */TDbWall *pLeft, TDbWall *pRight)
|
|
{
|
|
if (/*!pKa || */!pLeft || !pRight) return;
|
|
if (/*!pKa->isWriteEnabled() || */!pLeft->isWriteEnabled() || !pRight->isWriteEnabled()) return;
|
|
// pKa->addPersistentReactor(pLeft->objectId());
|
|
// pKa->addPersistentReactor(pRight->objectId());
|
|
pLeft->addPersistentReactor(pRight->objectId());
|
|
pRight->addPersistentReactor(pLeft->objectId());
|
|
}
|
|
|
|
void _RegisterReactor(CGlwKatana *pK)
|
|
{
|
|
if (pK && pK->isWriteEnabled())
|
|
{
|
|
OPENOBJ_BEGIN(pK->GetLeftWallID(), AcDb::kForWrite, TDbWall, pLeft)
|
|
OPENOBJ_BEGIN(pK->GetRightWallID(), AcDb::kForWrite, TDbWall, pRight)
|
|
if (pLeft && pRight)
|
|
_RegisterReactor(/*pK, */pLeft, pRight);
|
|
OPENOBJ_END()
|
|
OPENOBJ_END()
|
|
}
|
|
}
|
|
|
|
void _RegisterReactor(AcDbObjectId &kaID)
|
|
{
|
|
OPENOBJ_BEGIN(kaID, AcDb::kForWrite, CGlwKatana, pK)
|
|
if (pK)
|
|
_RegisterReactor(pK);
|
|
OPENOBJ_END()
|
|
}
|
|
|
|
|
|
AcDbObjectId _GetKatanaByWall(TDbWall *pWall, KAFLAG flag)
|
|
{
|
|
if (pWall)
|
|
{
|
|
switch (flag)
|
|
{
|
|
case eBegKatana:
|
|
return pWall->GetStartKatanaID();
|
|
case eEndKatana:
|
|
return pWall->GetEndKatanaID();
|
|
default:
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
}
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
AcDbObjectId _GetKatanaByWall(const AcDbObjectId &WallID, KAFLAG flag)
|
|
{
|
|
OPENOBJ_BEGIN(WallID, AcDb::kForWrite, TDbWall, pWall)
|
|
if (pWall)
|
|
return _GetKatanaByWall(pWall, flag);
|
|
OPENOBJ_END()
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
void _SetKatanaForWall(TDbWall *pWall, const AcDbObjectId &KaID, KAFLAG flag)
|
|
{
|
|
if (pWall)
|
|
{
|
|
switch (flag)
|
|
{
|
|
case eBegKatana:
|
|
pWall->SetStartKatanaID(KaID);
|
|
break;
|
|
case eEndKatana:
|
|
pWall->SetEndKatanaID(KaID);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void _SetKatanaForWall(const AcDbObjectId & WallID, const AcDbObjectId &KaID, KAFLAG flag)
|
|
{
|
|
OPENOBJ_BEGIN(WallID, AcDb::kForWrite, TDbWall, pWall)
|
|
if (pWall)
|
|
_SetKatanaForWall(pWall, KaID, flag);
|
|
OPENOBJ_END()
|
|
}
|
|
|
|
AcDbObjectId _GetWallByKatana(CGlwKatana *pKa, KAFLAG flag)
|
|
{
|
|
if (pKa)
|
|
{
|
|
switch (flag)
|
|
{
|
|
case eLeftWall:
|
|
return pKa->GetLeftWallID();
|
|
case eRightWall:
|
|
return pKa->GetRightWallID();
|
|
default:
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
}
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
AcDbObjectId _GetWallByKatana(AcDbObjectId &KaID, KAFLAG flag)
|
|
{
|
|
OPENOBJ_BEGIN(KaID, AcDb::kForWrite, CGlwKatana, pK)
|
|
if (pK)
|
|
return _GetWallByKatana(pK, flag);
|
|
OPENOBJ_END()
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
void _SetWallForKatana(CGlwKatana *pK, AcDbObjectId & WallID, KAFLAG flag)
|
|
{
|
|
if (pK)
|
|
{
|
|
switch (flag)
|
|
{
|
|
case eLeftWall:
|
|
pK->SetLeftWallID(WallID);
|
|
break;
|
|
case eRightWall:
|
|
pK->SetRightWallID(WallID);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void _SetWallForKatana(AcDbObjectId & WallID, AcDbObjectId &KaID, KAFLAG flag)
|
|
{
|
|
OPENOBJ_BEGIN(KaID, AcDb::kForWrite, CGlwKatana, pK)
|
|
if (pK)
|
|
_SetWallForKatana(pK, WallID, flag);
|
|
OPENOBJ_END()
|
|
}
|
|
|
|
void _ModifyKatana(CGlwKatana *pK)
|
|
{
|
|
if (!pK) return;
|
|
|
|
if (!pK->IsDragGripPt())
|
|
return;
|
|
else
|
|
pK->SetIsDragGripPt(false);
|
|
|
|
_UnRegisterReactor(pK);
|
|
OPENOBJ_BEGIN(pK->GetLeftWallID(), AcDb::kForWrite,TDbWall, pLWall)
|
|
OPENOBJ_BEGIN(pK->GetRightWallID(), AcDb::kForWrite,TDbWall, pRWall)
|
|
if (pRWall && pLWall)
|
|
{
|
|
AcDbLine line(pK->GetLeftPt(), pK->GetRightPt());
|
|
AcGePoint3dArray pts;
|
|
Acad::ErrorStatus es;
|
|
es = pLWall->intersectWith(&line, AcDb::kExtendThis, AcGePlane::kXYPlane, pts);
|
|
if (es != Acad::eOk) return;
|
|
if (pts.isEmpty()) return;
|
|
|
|
// 在 修改墙体长度之前,应把移动范围内的门窗与墙附件进行移动
|
|
TGGeCurveSegment segL(*pLWall), segR(*pRWall);
|
|
segL.SetPoints(segL.StartPoint(), pts[0]);
|
|
segR.SetPoints(pts[0], segR.EndPoint());
|
|
if (DOWN_ZERO(segL.GetLength() - pLWall->GetLength())) // 左墙变短,其上门窗移动到右墙上
|
|
{
|
|
TGGeCurveSegment seg(segL);
|
|
seg.SetPoints(pts[0], pLWall->EndPoint());
|
|
_ProcessOpeningAndPatch(pLWall, pRWall, seg);
|
|
}
|
|
else if (DOWN_ZERO(segR.GetLength() - pRWall->GetLength())) // 右墙变短,其上门窗移动到左墙上
|
|
{
|
|
TGGeCurveSegment seg(segR);
|
|
seg.SetPoints(pRWall->StartPoint(), pts[0]);
|
|
_ProcessOpeningAndPatch(pRWall, pLWall, seg);
|
|
}
|
|
else // 都未改变,则退出
|
|
return;
|
|
// end
|
|
|
|
pLWall->SetPoints(pLWall->StartPoint(), pts[0]);
|
|
pRWall->SetPoints(pts[0], pRWall->EndPoint());
|
|
}
|
|
OPENOBJ_END()
|
|
OPENOBJ_END()
|
|
_RegisterReactor(pK);
|
|
}
|
|
}
|
|
|
|
extern void InitGlwKatana(BOOL bInit)
|
|
{
|
|
if (bInit)
|
|
{
|
|
CGlwKatana::rxInit();
|
|
}
|
|
else
|
|
{
|
|
deleteAcRxClass(CGlwKatana::desc());
|
|
}
|
|
}
|
|
|
|
ACRX_DXF_DEFINE_MEMBERS(CGlwKatana, ATSCurveEntity, AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,
|
|
1, ATS_KATANA, "ATS_KATANA,图形无法解析, 请下载上华软件|网址: www.shanghuasoft.com");
|
|
|
|
IMPLEMENT_TENTBASE(CGlwKatana);
|
|
|
|
/*
|
|
.ptLeft
|
|
|---------------------------|
|
|
| .m_ptCenter |
|
|
|---------------------------|
|
|
.ptRight
|
|
*/
|
|
bool CGlwKatana::CalcTraitPtByWall(const AcGePoint3d &pt)
|
|
{
|
|
OPENOBJ_BEGIN(m_objLeftWall, AcDb::kForRead, TDbWall, pWall)
|
|
if (pWall)
|
|
{
|
|
TGGeCurveSegment lSide, rSide;
|
|
pWall->GetStandardCurve(lSide, rSide);
|
|
if (rSide.Is(CURVE_LINE))
|
|
{
|
|
TADSGePoint3d ptL, ptR;
|
|
lSide.ProjectToMe(pt, ptL);
|
|
rSide.ProjectToMe(pt, ptR);
|
|
m_ptRight = asPnt3d(ptR);
|
|
m_ptLeft = asPnt3d(ptL);
|
|
}
|
|
else if (rSide.Is(CURVE_ARC))
|
|
{
|
|
TGGeArc rArc = rSide.GetArc();
|
|
TGGeArc lArc = lSide.GetArc();
|
|
double rR = rArc.GetRadius();
|
|
double lR = lArc.GetRadius();
|
|
ads_point center;
|
|
rArc.Center(center);
|
|
AcGePoint3d ptCir = asPnt3d(center);
|
|
m_ptLeft = m_ptRight = ptCir;
|
|
AcGeVector3d v = pt - ptCir;
|
|
v.normalize();
|
|
v *= lR;
|
|
m_ptLeft += v;
|
|
v.normalize();
|
|
v *= rR;
|
|
m_ptRight += v;
|
|
|
|
}
|
|
m_ptCenter.x = (m_ptLeft.x + m_ptRight.x)*.5;
|
|
m_ptCenter.y = (m_ptLeft.y + m_ptRight.y)*.5;
|
|
m_ptCenter.z = (m_ptLeft.z + m_ptRight.z)*.5;
|
|
return true;
|
|
}
|
|
OPENOBJ_END()
|
|
return true;
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::dwgInFields( AcDbDwgFiler* pFiler )
|
|
{
|
|
assertWriteEnabled();
|
|
Acad::ErrorStatus es;
|
|
if ((es = TDbCurveEntity::dwgInFields(pFiler)) != Acad::eOk)
|
|
return es;
|
|
pFiler->readPoint3d(&m_ptCenter);
|
|
pFiler->readPoint3d(&m_ptLeft);
|
|
pFiler->readPoint3d(&m_ptRight);
|
|
|
|
pFiler->readItem(&m_objLeftWall);
|
|
pFiler->readItem(&m_objRightWall);
|
|
pFiler->readDouble(&m_dWallLessLength);
|
|
|
|
_RegisterReactor(this);
|
|
return pFiler->filerStatus();
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::dwgOutFields( AcDbDwgFiler* pFiler ) const
|
|
{
|
|
assertReadEnabled();
|
|
Acad::ErrorStatus es;
|
|
if ((es = TDbCurveEntity::dwgOutFields(pFiler)) != Acad::eOk)
|
|
return es;
|
|
pFiler->writePoint3d(m_ptCenter);
|
|
pFiler->writePoint3d(m_ptLeft);
|
|
pFiler->writePoint3d(m_ptRight);
|
|
pFiler->writeItem(m_objLeftWall);
|
|
pFiler->writeItem(m_objRightWall);
|
|
pFiler->writeDouble(m_dWallLessLength);
|
|
return pFiler->filerStatus();
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::ExplodeOrDraw2d( TGGiExplodeDrawBase &dc ) const
|
|
{
|
|
// 取左墙宽做为刀的长度
|
|
dc.DrawLine(TGGeLine(asDblArray(m_ptLeft), asDblArray(m_ptRight)));
|
|
return Acad::eOk;
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::ExplodeOrDraw3d( TGGiExplodeDrawBase &dc ) const
|
|
{
|
|
return ExplodeOrDraw2d(dc);
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::subTransformBy( const AcGeMatrix3d& xform )
|
|
{
|
|
assertWriteEnabled();
|
|
TDbCurveEntity::subTransformBy(xform);
|
|
|
|
m_ptCenter.transformBy(xform);
|
|
m_ptLeft.transformBy(xform);
|
|
m_ptRight.transformBy(xform);
|
|
return Acad::eOk;
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::subGetGripPoints( AcGePoint3dArray&gripPoints,AcDbIntArray&,AcDbIntArray& ) const
|
|
{
|
|
assertReadEnabled();
|
|
gripPoints.append(m_ptCenter);
|
|
gripPoints.append(m_ptLeft);
|
|
gripPoints.append(m_ptRight);
|
|
return Acad::eOk;
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::subMoveGripPointsAt( const AcDbIntArray& indices, const AcGeVector3d& offset )
|
|
{
|
|
assertWriteEnabled();
|
|
//subTransformBy(offset);
|
|
|
|
m_ptCenter.transformBy(offset);
|
|
m_ptLeft.transformBy(offset);
|
|
m_ptRight.transformBy(offset);
|
|
|
|
double dOffset(m_dWallLessLength);
|
|
TADSGePoint3d ptNew; // 投影到墙基线上的点
|
|
static bool bLeft(false);
|
|
OPENOBJ_BEGIN(m_objLeftWall, AcDb::kForRead, TDbWall, pLWall)
|
|
if (pLWall)
|
|
{
|
|
OPENOBJ_BEGIN(m_objRightWall, AcDb::kForRead, TDbWall, pRWall)
|
|
if (pRWall)
|
|
{
|
|
bool bStartPt(false);
|
|
bool bResetPt(false);
|
|
TGGeCurveSegment segL(*pLWall), segR(*pRWall), segAll(*pLWall);
|
|
segAll.SetPoints(segL.StartPoint(), segR.EndPoint());
|
|
segAll.ProjectToMe(m_ptCenter, ptNew);
|
|
do
|
|
{
|
|
if ((ptNew & segL) == PR_INSIDE) // 左侧墙上
|
|
{
|
|
bLeft = true;
|
|
// 先判断是否在门窗或patch上
|
|
if (_JudgePtInOpeningAndPatch(pLWall, ptNew, ptNew))
|
|
break;
|
|
// 再判断是否越界
|
|
if (_JudgePtInWall(pLWall, ptNew, ptNew, dOffset, true))
|
|
break;
|
|
}
|
|
else if ((ptNew & segR) == PR_INSIDE) // 右侧墙上
|
|
{
|
|
bLeft = false;
|
|
// 先判断是否在门窗或patch上
|
|
if (_JudgePtInOpeningAndPatch(pRWall, ptNew, ptNew))
|
|
break;
|
|
// 再判断是否越界
|
|
if (_JudgePtInWall(pRWall, ptNew, ptNew, dOffset, false))
|
|
break;
|
|
}
|
|
else if ((ptNew & segL) == PR_ONPT2 || (ptNew & segR) == PR_ONPT1)
|
|
{
|
|
break;
|
|
}
|
|
else // 不在墙上
|
|
{
|
|
if (bLeft)
|
|
_JudgePtInWall(pLWall, ptNew, ptNew, dOffset, true);
|
|
else
|
|
_JudgePtInWall(pRWall, ptNew, ptNew, dOffset, false);
|
|
break;
|
|
}
|
|
} while (false);
|
|
CalcTraitPtByWall(asPnt3d(ptNew));
|
|
m_bDragGripPt = true;
|
|
}
|
|
OPENOBJ_END()
|
|
}
|
|
OPENOBJ_END()
|
|
|
|
return Acad::eOk;
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::subDeepClone( AcDbObject *pOwner,
|
|
AcDbObject *&pClonedObject,
|
|
AcDbIdMapping& idMap,
|
|
Adesk::Boolean isPrimary ) const
|
|
{
|
|
Acad::ErrorStatus es = TDbCurveEntity::subDeepClone(pOwner, pClonedObject, idMap, isPrimary);
|
|
if (es != Acad::eOk) return es;
|
|
AcDb::DeepCloneType dt = idMap.deepCloneContext();
|
|
if (dt != AcDb::kDcCopy/* && dt != AcDb::kDcExplode*/) return es;
|
|
if (m_objLeftWall.isNull() || m_objRightWall.isNull()) return Acad::eNullHandle;
|
|
|
|
AcDbObjectId id_newLeft = FindCloneId(m_objLeftWall, pOwner, idMap, isPrimary, true);
|
|
AcDbObjectId id_newRight = FindCloneId(m_objRightWall, pOwner, idMap, isPrimary, true);
|
|
|
|
if (UpdateNewKatana((CGlwKatana*)pClonedObject, id_newLeft, id_newRight))
|
|
g_deepCloneKatanas.push_back(pClonedObject->objectId());
|
|
|
|
return Acad::eOk;
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::subWblockClone( AcRxObject* pOwner, AcDbObject*& pClonedObject, AcDbIdMapping& idMap, Adesk::Boolean isPrimary ) const
|
|
{
|
|
Acad::ErrorStatus es = TDbCurveEntity::subWblockClone(pOwner, pClonedObject, idMap, isPrimary);
|
|
if (Acad::eOk != es) return es;
|
|
if (!m_objLeftWall || !m_objRightWall) return Acad::eNullHandle;
|
|
|
|
AcDbObjectId id_newLeft = FindCloneId(m_objLeftWall, pOwner, idMap, isPrimary, false);
|
|
AcDbObjectId id_newRight = FindCloneId(m_objRightWall, pOwner, idMap, isPrimary, false);
|
|
|
|
UpdateNewKatana((CGlwKatana*)pClonedObject, id_newLeft, id_newRight);
|
|
|
|
return Acad::eOk;
|
|
}
|
|
|
|
AcDbObjectId CGlwKatana::FindCloneId( AcDbObjectId id,
|
|
AcRxObject* pOwner,
|
|
AcDbIdMapping& idMap,
|
|
Adesk::Boolean isPrimary,
|
|
bool bIsDeepClone) const
|
|
{
|
|
AcDbIdPair idPair(id, AcDbObjectId::kNull, false, isPrimary ? true : false);
|
|
if (!idMap.compute(idPair))
|
|
{
|
|
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbObject, pObj)
|
|
if (pObj)
|
|
{
|
|
AcDbObject *pCloned(NULL);
|
|
Acad::ErrorStatus es = Acad::eOk;
|
|
if (bIsDeepClone)
|
|
es = pObj->deepClone((AcDbObject*)pOwner, pCloned, idMap, isPrimary);
|
|
else
|
|
es = pObj->wblockClone(pOwner, pCloned, idMap, isPrimary);
|
|
if (es == Acad::eOk)
|
|
{
|
|
AcDbObjectId id = pCloned->objectId();
|
|
pCloned->close();
|
|
return id;
|
|
}
|
|
}
|
|
OPENOBJ_END()
|
|
}
|
|
else
|
|
return idPair.value();
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
bool CGlwKatana::UpdateNewKatana(CGlwKatana *pNewKa, AcDbObjectId idLeft, AcDbObjectId idRight ) const
|
|
{
|
|
if (!pNewKa || !idLeft.isValid() || !idRight.isValid()) return false;
|
|
pNewKa->m_objLeftWall = idLeft;
|
|
pNewKa->m_objRightWall = idRight;
|
|
OPENOBJ_BEGIN(idLeft, AcDb::kForWrite, TDbWall, pWall)
|
|
if (pWall)
|
|
pWall->SetEndKatanaID(pNewKa->objectId());
|
|
OPENOBJ_END()
|
|
OPENOBJ_BEGIN(idRight, AcDb::kForWrite, TDbWall, pWall)
|
|
if (pWall)
|
|
pWall->SetStartKatanaID(pNewKa->objectId());
|
|
OPENOBJ_END()
|
|
_RegisterReactor(pNewKa);
|
|
return true;
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::GetExtents2d( TADSGePoint3d &ptLow, TADSGePoint3d &ptUp ) const
|
|
{
|
|
GetExtents(ptLow, ptUp);
|
|
ptLow.z = ptUp.z = 0;
|
|
return Acad::eOk;
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::GetExtents( TADSGePoint3d &ptLow, TADSGePoint3d &ptUp ) const
|
|
{
|
|
AcDbExtents ext;
|
|
ext.addPoint(m_ptRight);
|
|
ext.addPoint(m_ptLeft);
|
|
ptLow = ext.minPoint();
|
|
ptUp = ext.maxPoint();
|
|
return Acad::eOk;
|
|
}
|
|
|
|
Acad::ErrorStatus CGlwKatana::subErase( Adesk::Boolean erasing )
|
|
{
|
|
if (erasing) // 删除
|
|
{
|
|
AcDbObjectId idNull(AcDbObjectId::kNull);
|
|
_UnRegisterReactor(this);
|
|
_SetKatanaForWall(_GetWallByKatana(this, eLeftWall), idNull, eEndKatana);
|
|
_SetKatanaForWall(_GetWallByKatana(this, eRightWall), idNull, eBegKatana);
|
|
}
|
|
else // 恢复
|
|
{
|
|
_RegisterReactor(this);
|
|
_SetKatanaForWall(_GetWallByKatana(this, eLeftWall), objectId(), eEndKatana);
|
|
_SetKatanaForWall(_GetWallByKatana(this, eRightWall), objectId(), eBegKatana);
|
|
}
|
|
return Acad::eOk;
|
|
}
|
|
|
|
void CGlwKatana::Init( AcDbObjectId &idNew, AcDbObjectId &idOld )
|
|
{
|
|
AcGePoint3d ptCnt(AcGePoint3d::kOrigin);
|
|
AcDbObjectId idLeft(AcDbObjectId::kNull), idRight(AcDbObjectId::kNull);
|
|
OPENOBJ_BEGIN(idNew, AcDb::kForWrite, TDbWall, pNew)
|
|
OPENOBJ_BEGIN(idOld, AcDb::kForWrite, TDbWall, pOld)
|
|
if (pNew && pOld)
|
|
{
|
|
if (pNew->EndPoint() == pOld->StartPoint())
|
|
{
|
|
ptCnt = pNew->EndPoint();
|
|
idLeft = pNew->objectId();
|
|
idRight = pOld->objectId();
|
|
}
|
|
else if (pNew->StartPoint() == pOld->EndPoint())
|
|
{
|
|
ptCnt = pOld->EndPoint();
|
|
idLeft = pOld->objectId();
|
|
idRight = pNew->objectId();
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
OPENOBJ_END()
|
|
OPENOBJ_END()
|
|
|
|
SetLeftWallID(idLeft);
|
|
SetRightWallID(idRight);
|
|
_SetKatanaForWall(idLeft, objectId(), eEndKatana);
|
|
_SetKatanaForWall(idRight, objectId(), eBegKatana);
|
|
|
|
_RegisterReactor(this);
|
|
CalcTraitPtByWall(ptCnt);
|
|
}
|
|
|
|
double CGlwKatana::GetLessLength()
|
|
{
|
|
return m_dWallLessLength;
|
|
}
|
|
|
|
int CGlwKatana::GetFirstVersion() const
|
|
{
|
|
return 10;
|
|
}
|
|
|
|
double CGlwKatana::m_dWallLessLength = 100;
|
|
|
|
AcDbObjectId KatanaToolkit::GetKatanaByTwoWalls( TDbWall *pWall1, TDbWall *pWall2 )
|
|
{
|
|
if (!pWall2 || !pWall1) return AcDbObjectId::kNull;
|
|
if (pWall1->GetStartKatanaID() == pWall2->GetEndKatanaID() && !pWall1->GetStartKatanaID().isNull())
|
|
return pWall1->GetStartKatanaID();
|
|
else if (pWall1->GetEndKatanaID() == pWall2->GetStartKatanaID() && !pWall1->GetEndKatanaID().isNull())
|
|
return pWall1->GetEndKatanaID();
|
|
else
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
bool KatanaToolkit::JudgeCollinearByWalls( TDbWall *pWall1, TDbWall *pWall2 )
|
|
{
|
|
if (!pWall2 || !pWall1) return false;
|
|
return _JudgeCollinear(pWall1, pWall2);
|
|
}
|
|
|
|
void KatanaToolkit::Erase( AcDbObjectId id )
|
|
{
|
|
OPENOBJ_BEGIN(id, AcDb::kForWrite, AcDbEntity, pEnt)
|
|
if (pEnt)
|
|
pEnt->erase();
|
|
OPENOBJ_END()
|
|
}
|
|
|
|
void KatanaToolkit::ModifyKatana( CGlwKatana *pKa )
|
|
{
|
|
_ModifyKatana(pKa);
|
|
}
|
|
|
|
void KatanaToolkit::SetBegKatanaIdForWall( TWallData *pWall, AcDbObjectId KaID )
|
|
{
|
|
if (pWall)
|
|
pWall->SetStartKatanaID(KaID);
|
|
}
|
|
|
|
void KatanaToolkit::SetEndKatanaIdForWall( TWallData *pWall, AcDbObjectId KaID )
|
|
{
|
|
if (pWall)
|
|
pWall->SetEndKatanaID(KaID);
|
|
}
|
|
|
|
AcDbObjectId KatanaToolkit::GetBegKatanaIdByWall( TDbWall *pWall )
|
|
{
|
|
if (pWall)
|
|
return pWall->GetStartKatanaID();
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
AcDbObjectId KatanaToolkit::GetEndKatanaIdByWall( TDbWall *pWall )
|
|
{
|
|
if (pWall)
|
|
return pWall->GetEndKatanaID();
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
void KatanaToolkit::SetLeftWallIdForKatana( AcDbObjectId wallID, AcDbObjectId KaID )
|
|
{
|
|
OPENOBJ_BEGIN(KaID, AcDb::kForWrite, CGlwKatana, pKa)
|
|
if (pKa)
|
|
pKa->SetLeftWallID(wallID);
|
|
OPENOBJ_END()
|
|
}
|
|
|
|
void KatanaToolkit::SetRightWallIdForKatana( AcDbObjectId wallID, AcDbObjectId KaID )
|
|
{
|
|
OPENOBJ_BEGIN(KaID, AcDb::kForWrite, CGlwKatana, pKa)
|
|
if (pKa)
|
|
pKa->SetRightWallID(wallID);
|
|
OPENOBJ_END()
|
|
}
|
|
|
|
AcDbObjectId KatanaToolkit::GetLeftWallIdByKatana( AcDbObjectId KaID )
|
|
{
|
|
OPENOBJ_BEGIN(KaID, AcDb::kForWrite, CGlwKatana, pKa)
|
|
if (pKa)
|
|
return pKa->GetLeftWallID();
|
|
OPENOBJ_END()
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
AcDbObjectId KatanaToolkit::GetRightWallIdByKatana( AcDbObjectId KaID )
|
|
{
|
|
OPENOBJ_BEGIN(KaID, AcDb::kForWrite, CGlwKatana, pKa)
|
|
if (pKa)
|
|
return pKa->GetRightWallID();
|
|
OPENOBJ_END()
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
void KatanaToolkit::UnRegister( TDbWall *pWall, AcDbObjectId idOther )
|
|
{
|
|
OPENOBJ_BEGIN(idOther, AcDb::kForWrite, TDbWall, pOther)
|
|
if (pOther)
|
|
_UnRegisterReactor(pWall, pOther);
|
|
OPENOBJ_END()
|
|
}
|
|
|
|
void KatanaToolkit::Register( TDbWall *pWall, AcDbObjectId idOther )
|
|
{
|
|
OPENOBJ_BEGIN(idOther, AcDb::kForWrite, TDbWall, pOther)
|
|
if (pOther)
|
|
_RegisterReactor(pWall, pOther);
|
|
OPENOBJ_END()
|
|
}
|
|
|
|
AcDbObjectId KatanaToolkit::GetOtherWallByKatana( TDbWall *pWall, AcDbObjectId KaID )
|
|
{
|
|
if (!pWall || KaID.isNull()) return AcDbObjectId::kNull;
|
|
|
|
if (pWall->GetEndKatanaID() == KaID)
|
|
{
|
|
OPENOBJ_BEGIN(KaID, AcDb::kForRead, CGlwKatana, pKa)
|
|
if (pKa)
|
|
return pKa->GetRightWallID();
|
|
OPENOBJ_END()
|
|
}
|
|
else if (pWall->GetStartKatanaID() == KaID)
|
|
{
|
|
OPENOBJ_BEGIN(KaID, AcDb::kForRead, CGlwKatana, pKa)
|
|
if (pKa)
|
|
return pKa->GetLeftWallID();
|
|
OPENOBJ_END()
|
|
}
|
|
return AcDbObjectId::kNull;
|
|
}
|
|
|
|
CString KatanaToolkit::GetCMDName()
|
|
{
|
|
TCString sCmd;
|
|
TGGetVar(_T("CMDNAMES"), sCmd);
|
|
return sCmd.cs();
|
|
}
|