#include "stdafx.h" #include "aecdbmultipartentity.h" #include "simpleproperty.h" #include "coretools.h" #include "SectionPerfCounter.h" #include "dbacis.h" IMP_XDATA_KEY(AecDbMultiPartEntity,_ptOrg_); IMP_XDATA_KEY(AecDbMultiPartEntity,_vtX_); IMP_XDATA_KEY(AecDbMultiPartEntity,_vtY_); IMP_XDATA_KEY(AecDbMultiPartEntity,_vtZ_); extern void DLLIMPEXP OrthoProjected3DSolid(AcDb3dSolid* pSolidClone,const AcGePlane& plan,AcGeMatrix3d& xformPlanToWorld,AcDbVoidPtrArray& arEntPtrs); extern void DLLIMPEXP OrthoProjected3DSubMesh(AcDbSubDMesh* pSubMesh,const AcGePlane& plan,AcGeMatrix3d& xformPlanToWorld,AcDbVoidPtrArray& arEntPtrs); // 版本号保持 4(与已有图纸一致)。缓存块用 magic 自描述: // - 老图纸(v3)/ 别人写的 v4(无 magic):读不到 magic 就当没有缓存,照旧重建; // - 本版本写的 v4(有 magic):直接用块里的 ASM 几何。 // 代价:v3 的老版本插件打开 v4 图仍会走 eMakeMeProxy(这是升版本号本身带来的)。 Adesk::UInt32 AecDbMultiPartEntity::kCurrentVersionNumber = 4; #ifdef AEC_HAS_MODELER_FILER namespace { const Adesk::UInt32 kMp3dMagic = 0x50443341; // 'A3DP' const Adesk::UInt32 kMp3dEnd = 0x50443341 ^ 0xFFFFFFFF; const Adesk::UInt16 kMp3dBlkVer = 1; } #endif ACRX_DXF_DEFINE_MEMBERS (AecDbMultiPartEntity, AecDbBDPipeBase, AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, AcDbProxyEntity::kNoOperation | AcDbProxyEntity::kDisableProxyWarning, AEC_MULTIPARTENT, "AecDbMultiPartEntity" "|Product Desc: shanghua earthworm app obj" "|Company: shanghua inc" "|WEB Address: www.shanghuasoft.com") AecDbMultiPartEntity::AecDbMultiPartEntity(void) { } AecDbMultiPartEntity::~AecDbMultiPartEntity(void) { } Acad::ErrorStatus AecDbMultiPartEntity::Draw2d(AcGiDraw &dc) const { assertReadEnabled(); return Draw3d(dc); } Acad::ErrorStatus AecDbMultiPartEntity::Draw3d(AcGiDraw &dc) const { assertReadEnabled(); //AEC_PERF_COUNTER=1 的 Debug 下计时:这类实体开图期画 3D 一共花多少(缓存收益的天花板) SectionPerf::Scope perfScope("MultiPartEntity::Draw3d"); const bool bHadCache = Has3DBuffer(); SectionPerf::Scope cacheScope(bHadCache ? "MultiPartEntity::Draw3d.cached" : "MultiPartEntity::Draw3d.build"); AecDbBDPipeBase::Draw3d(dc); AcGePoint3d ptOrg = GetOrg(); // 以ptOrg为中心,边长100,画一个十字,在当前的UCS上 AcGeVector3d vtX(GetXDir()); AcGeVector3d vtY(GetYDir()); AcGeVector3d vtZ(GetZDir()); double len(1000.); AcGePoint3d pt1(ptOrg); pt1 += vtY * len * .5; AcGePoint3d pt2(pt1 - vtY * len); AcGePoint3d pt3(ptOrg - vtX * len * .5); AcGePoint3d pt4(pt3 + vtX * len); if (m_arX3DPartPtrs.isEmpty()) { uint oldClr = dc.GetColor(); dc.SetColor(1); dc.DrawLine(AcGeLineSeg3d(pt1, pt2)); dc.DrawLine(AcGeLineSeg3d(pt3, pt4)); dc.SetColor(oldClr); } return Acad::eOk; } Acad::ErrorStatus AecDbMultiPartEntity::subGetGripPoints(AcDbGripDataPtrArray& grips, const double curViewUnitSize, const int gripSize, const AcGeVector3d& curViewDir, const int bitflags) const { return Acad::eNotImplementedYet; } Acad::ErrorStatus AecDbMultiPartEntity::subGetGripPoints(AcGePoint3dArray &gripPoints, AcDbIntArray &osnapModes, AcDbIntArray &geomIds) const { assertReadEnabled(); gripPoints.append(GetOrg()); return Acad::eOk; } Acad::ErrorStatus AecDbMultiPartEntity::SubAddDimPoints(AcDbGripDataPtrArray& grips,const AcGeVector3d& curViewDir) const { return Acad::eOk; } EPosition AecDbMultiPartEntity::ExplainGripIndex(int nIndex,CString& sTip) const { assertReadEnabled(); EPosition ePos = eStart; return ePos; } Acad::ErrorStatus AecDbMultiPartEntity::ImpGetGripPoints(AcGePoint3dArray& gripPoints,const int bitflags) const { assertReadEnabled(); return Acad::eOk; } Acad::ErrorStatus AecDbMultiPartEntity::subMoveGripPointsAt(const AcDbVoidPtrArray& gripAppData, const AcGeVector3d& offset, const int bitflags) { AssertWriteEnabled(); return Acad::eOk; } Acad::ErrorStatus AecDbMultiPartEntity::subMoveGripPointsAt(const AcDbIntArray &indices, const AcGeVector3d &offset) { AssertWriteEnabled(); AcGeMatrix3d mat; mat.setToTranslation(offset); return subTransformBy(mat); } Acad::ErrorStatus AecDbMultiPartEntity::subGetStretchPoints(AcGePoint3dArray& stretchPoints) const { assertReadEnabled(); stretchPoints.append(GetOrg()); return Acad::eOk; } Acad::ErrorStatus AecDbMultiPartEntity::subMoveStretchPointsAt(const AcDbIntArray& indices,const AcGeVector3d& offset) { AssertWriteEnabled(); AcGeMatrix3d mat; mat.setToTranslation(offset); return subTransformBy(mat); } Acad::ErrorStatus AecDbMultiPartEntity::copyFrom(const AcRxObject * pSrc) { return Acad::eOk; } Acad::ErrorStatus AecDbMultiPartEntity::subTransformBy(const AcGeMatrix3d &xform) { AecDbBDPipeBase::subTransformBy(xform); AcGePoint3d pt(GetOrg()); pt.transformBy(xform); SetOrg(pt); return Acad::eOk; } Acad::ErrorStatus AecDbMultiPartEntity::subGetOsnapPoints(AcDb::OsnapMode osnapMode , INT_PTR gsSelectionMark , const AcGePoint3d &pickPoint , const AcGePoint3d &lastPoint , const AcGeMatrix3d &viewXform , AcGePoint3dArray &snapPoints , AcDbIntArray &geomIds) const { assertReadEnabled(); AcGePoint3d ptOrg = GetOrg(); // 以ptOrg为中心,边长100,画一个十字,在当前的UCS上 AcGeVector3d vtX(GetXDir()); AcGeVector3d vtY(GetYDir()); AcGeVector3d vtZ(GetZDir()); double len(1000.); AcGePoint3d pt1(ptOrg); pt1 += vtY * len * .5; AcGePoint3d pt2(pt1 - vtY * len); AcGePoint3d pt3(ptOrg - vtX * len * .5); AcGePoint3d pt4(pt3 + vtX * len); AcDbLine l1(pt1, pt2); l1.getOsnapPoints(osnapMode, gsSelectionMark, pickPoint, lastPoint, viewXform, snapPoints, geomIds); AcDbLine l2(pt3, pt4); l2.getOsnapPoints(osnapMode, gsSelectionMark, pickPoint, lastPoint, viewXform, snapPoints, geomIds); const AcDbVoidPtrArray &ar = Get3DBuffer(); for (int i = 0; i < ar.length(); ++i) { AcDbEntity *pEnt((AcDbEntity*)ar[i]); pEnt->getOsnapPoints(osnapMode, gsSelectionMark, pickPoint, lastPoint, viewXform, snapPoints, geomIds); } return Acad::eOk; } void AecDbMultiPartEntity::subList() const { assertReadEnabled(); acutPrintf(_T("\n异形构筑物:")); AecDbBDPipeBase::subList(); } int AecDbMultiPartEntity::GetDraw2dables(Adesk::UInt16 nDrawStyle, AcDbVoidPtrArray & arEntPtrs) const { assertReadEnabled(); AcDbObjectId id = objectId(); AcDbEntity* pEnt = NULL; const AcDbVoidPtrArray &ar2D = Get2DBuffer(); if (ar2D.isEmpty()) { AcGePlane plan = AcGePlane::kXYPlane; AcGeMatrix3d xform; xform.setToPlaneToWorld(plan); xform.invert(); AcDbVoidPtrArray arSubEntPtrs; AcDb3dSolid* pSolid = NULL; AcDbSubDMesh* pSubMesh = NULL; const AcDbVoidPtrArray &ar3D = Get3DBuffer(); for (int i = 0;i < ar3D.length();i++) { pEnt = (AcDbEntity*)ar3D.at(i); pSolid = AcDb3dSolid::cast(pEnt); if (pSolid != NULL) { //投影法 OrthoProjected3DSolid(pSolid, plan, xform, arSubEntPtrs); } pSubMesh = AcDbSubDMesh::cast(pEnt); if (pSubMesh != NULL) { OrthoProjected3DSubMesh(pSubMesh, plan, xform, arSubEntPtrs); } } AcDbObjectId idLayer = layerId(); for (int i = 0;i < arSubEntPtrs.length();i++) { pEnt = (AcDbEntity*)arSubEntPtrs.at(i); pEnt->setLayer(idLayer); arEntPtrs.append(pEnt); } } else { AcGePlane plan = AcGePlane::kXYPlane; AcGeMatrix3d xform; xform.setToPlaneToWorld(plan); xform.invert(); AcDbVoidPtrArray arSubEntPtrs; AcDb3dSolid* pSolid = NULL; AcDbSubDMesh* pSubMesh = NULL; AcDbEntity* pClnEnt = NULL; AcDbObjectId idLayer = layerId(); for (int i = 0;i < ar2D.length();i++) { pEnt = (AcDbEntity*)ar2D.at(i); pClnEnt = (AcDbEntity*)pEnt->clone(); pClnEnt->setLayer(idLayer); pSolid = AcDb3dSolid::cast(pClnEnt); if (pSolid != NULL) { //投影法 OrthoProjected3DSolid(pSolid, plan, xform, arSubEntPtrs); continue; } pSubMesh = AcDbSubDMesh::cast(pClnEnt); if (pSubMesh != NULL) { OrthoProjected3DSubMesh(pSubMesh, plan, xform, arSubEntPtrs); continue; } arSubEntPtrs.append(pClnEnt); } for (int i = 0;i < arSubEntPtrs.length();i++) { pEnt = (AcDbEntity*)arSubEntPtrs.at(i); pEnt->setLayer(idLayer); arEntPtrs.append(pEnt); } } return arEntPtrs.length(); } int AecDbMultiPartEntity::GetDraw3dables(AcDbVoidPtrArray & arEntPtrs, bool bWriteBimInfo) const { assertReadEnabled(); AcDbEntity* pEnt = NULL, *pEntClone = NULL; const AcDbVoidPtrArray &ar3D = Get3DBuffer(); for (int i = 0;i < ar3D.length();i++) { pEnt = (AcDbEntity*)ar3D.at(i); pEntClone = (AcDbEntity*)pEnt->clone(); if (bWriteBimInfo) { m_mapSpecXData.Write(pEntClone, _T("BIMDATA")); } pEntClone->setLayer(layerId()); arEntPtrs.append(pEntClone); } return arEntPtrs.length(); } Acad::ErrorStatus AecDbMultiPartEntity::dwgInFields (AcDbDwgFiler* pFiler) { AssertWriteEnabled(); //----- Read parent class information first. Acad::ErrorStatus es = AecDbBDPipeBase::dwgInFields (pFiler) ; if ( es != Acad::eOk ) return (es) ; //----- Object version number needs to be read first Adesk::UInt32 version = 0 ; if ( (es =pFiler->readUInt32 (&version)) != Acad::eOk ) return (es) ; if ( version > AecDbMultiPartEntity::kCurrentVersionNumber ) return (Acad::eMakeMeProxy); if (version == 2) { //临时 AecDbObjXDataMap xMap; xMap.dwgInFields(pFiler); } #ifdef AEC_HAS_MODELER_FILER // ---- 3D 几何缓存块(modeler filer)---- // 位置:本实体流的**末尾**(这个类在 version 之后不写任何自己的字段, // 所以老版本读到自己需要的字段就停,尾部多出来的字节会被忽略)。 // 为什么不用升版本号:升了会让老版本 `version > kCurrentVersionNumber` // 直接 eMakeMeProxy —— 整批实体变代理对象(实测已出现过 ZOMBIEENTITY)。 // 所以这里用 magic 自描述:读不到 magic 就当没有缓存,照旧重建。 { Adesk::UInt32 nMagic = 0; if (pFiler->readUInt32(&nMagic) == Acad::eOk && nMagic == kMp3dMagic) { Adesk::UInt16 nBlkVer = 0; Adesk::Int32 nCount = 0; if (pFiler->readUInt16(&nBlkVer) == Acad::eOk && nBlkVer == kMp3dBlkVer && pFiler->readInt32(&nCount) == Acad::eOk && nCount > 0 && nCount <= 64) { int nModelerVer = -1; int nOk = 0; for (int i = 0; i < nCount; ++i) { ENTITY* pAsm = NULL; if (acdbModelerRestoreEntityFromDwgFiler(pFiler, pAsm, &nModelerVer, kReadStrangerEntityDefault) != Acad::eOk || pAsm == NULL) break; AcDb3dSolid* pSolid = new AcDb3dSolid(); if (pSolid->setASMBody(pAsm) != Acad::eOk) { delete pSolid; break; } Add3DBuffer(pSolid); ++nOk; } Adesk::UInt32 nEnd = 0; const bool bEndOk = (pFiler->readUInt32(&nEnd) == Acad::eOk && nEnd == kMp3dEnd); if (nOk != (int)nCount || !bEndOk) { // 半成品块:整条丢弃,回退重建 Clean3DBuffer(); } } } } #endif return Acad::eOk; // 探测缓存块时 readUInt32 在老图上会把状态置成 eEndOfFile, // 这里显式返回 eOk,否则整个实体会被判成读取失败 } Acad::ErrorStatus AecDbMultiPartEntity::dwgOutFields(AcDbDwgFiler* pFiler) const { assertReadEnabled(); //----- Save parent class information first. Acad::ErrorStatus es = AecDbBDPipeBase::dwgOutFields (pFiler) ; if ( es != Acad::eOk ) return (es) ; //----- Object version number needs to be saved first if ( (es =pFiler->writeUInt32 (AecDbMultiPartEntity::kCurrentVersionNumber)) != Acad::eOk ) return (es) ; #ifdef AEC_HAS_MODELER_FILER // ---- 3D 几何缓存块:只存 brep(AcDb3dSolid),且**count 按实际写入数**记 ---- // 不能写 Get3DBuffer().length():缓存里可能有中心线/网格等非 brep, // 那些会被跳过,count 与实际 payload 数不一致 → 读端多吃数据、实体流损坏。 { // 先一次性锁住、收集 body,写入期间不放锁 —— 这样 count 一定等于实际写出的条数 AcArray arSolids; AcArray arAsm; const AcDbVoidPtrArray& arBuf = Get3DBuffer(); for (int i = 0; i < arBuf.length(); ++i) { AcDb3dSolid* pSolid = AcDb3dSolid::cast((AcDbEntity*)arBuf[i]); if (pSolid == NULL) continue; ENTITY* pAsm = (ENTITY*)pSolid->getLockedASMBody(); if (pAsm == NULL) continue; arSolids.append(pSolid); arAsm.append(pAsm); } if (!arSolids.isEmpty()) { AcDbDatabase* pDb = GetMe()->database(); if (pDb == NULL) pDb = acdbHostApplicationServices()->workingDatabase(); pFiler->writeUInt32(kMp3dMagic); pFiler->writeUInt16(kMp3dBlkVer); pFiler->writeInt32((Adesk::Int32)arSolids.length()); for (int i = 0; i < arSolids.length(); ++i) { const Acad::ErrorStatus esSave = acdbModelerSaveEntityToDwgFiler(pFiler, arAsm[i], pDb, -1); arSolids[i]->unlockASMBody(); if (esSave != Acad::eOk) break; } pFiler->writeUInt32(kMp3dEnd); } } #endif return pFiler->filerStatus(); } Acad::ErrorStatus AecDbMultiPartEntity::dxfInFields (AcDbDxfFiler* pFiler) { return Acad::eOk; } Acad::ErrorStatus AecDbMultiPartEntity::dxfOutFields(AcDbDxfFiler* pFiler) const { return Acad::eOk; } int AecDbMultiPartEntity::ComparedTo(AecDbCurveBase* pCurOther) const { assertReadEnabled(); return -1; } SHJson::WValue& AecDbMultiPartEntity::ToJson(bool bExprotGeo) const { assertReadEnabled(); return AecDbBDPipeBase::ToJson(bExprotGeo); } bool AecDbMultiPartEntity::ByJson(const SHJson::WValue &v) { AssertWriteEnabled(); return AecDbBDPipeBase::ByJson(v); } #include "HlrCutOption.h" void AecDbMultiPartEntity::ProcessHlrResult(const AcArray &ar , const std::map> &preAr , AcArray &output) const { HlrCutOption::ProcessHlrResult(this , FALSE , .0 , HlrCutOption::getHlrBLK_YGDT() , ar , preAr , output); } bool AecDbMultiPartEntity::GetProperties(SimpleProperty::PropertySetByIndex & porpertys) const { AecDbBDPipeBase::GetProperties(porpertys); CoreTools::setLayerPorperty(porpertys); CoreTools::setSubSystemPorperty(porpertys); CString sName(_T("异形构筑")); BOOL bPMFY(FALSE), bDLJC(FALSE); if (GetSpecialtyData()->GetAt(_T("PMFY"), bPMFY)) sName = _T("平面放样"); else if (GetSpecialtyData()->GetAt(_T("DLJC"), bDLJC)) sName = _T("板基础"); SimpleProperty::makeAndInsert(porpertys, _T("类型"), sName, false); return true; }