#include "StdAfx.h" #include "TGKatana.h" #include "TArchPerDocData.h" #include "TArchDocReactor.h" #include "TArchAppDocGlobals.h" static std::vector 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* plstO = const_cast< TDPtrList* >(&(pWall->GetOpeningIdList())); TDPtrList* plstP = const_cast< TDPtrList* >(&(pWall->GetPatchIdList())); TDPtrList 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* plstO = const_cast< TDPtrList* >(&(pSrc->GetOpeningIdList())); TDPtrList* plstP = const_cast< TDPtrList* >(&(pSrc->GetPatchIdList())); TDPtrList lstO, lstP; lstO.copyFrom(*plstO); lstP.copyFrom(*plstP); lstO << lstP; std::vector 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(); }