#include "StdAfx.h" #include "ent2db.h" #include #include "TSQLite.h" #include "shjson.h" #include "KTCADUtilityEx.h" #include "KTCadUtility.h" #include "geometry2json.h" #include "CoreTools.h" #include "AecDbWall.h" #include "AecDbBeam.h" #include "AecDbSlab.h" #include "AecDbColumn.h" #include "AecDbEwEquipment.h" #include "AecDbParamEquipment.h" #include "AecDbFlume.h" #include "AecDbRiverGroove.h" #include "AecDbEwPipe.h" #include "aecdbewfitting.h" #include "AecDbHvacDuct.h" #include "AecDbHvacFitting.h" #include "AecDbECableTray.h" #include "aecdbecfitting.h" #include "AecDbX3dPartEntity.h" #include "AecDbOpening.h" #include "AecDbHolder.h" #include "AecDbBossHolder.h" #include "AecDbhanger.h" #include "AecDbXEquipment.h" #include "AecDbClimbStair.h" #include "AecDbZLineStair.h" #include "AecDbMRPLineStair.h" #include "AecDbCornerStair.h" #include "AecDbCrossStair.h" #include "AecDbDoubleMulStair.h" #include "AecDbLineSegStair.h" #include "AecDbParaLlelStair.h" #include "AecDbRectCornerStair.h" #include "AecDbScissorsStair.h" #include "AecDbTriangleStair.h" using namespace SHJson; namespace ENT2DB { const CString g_dbName(_T("\\sh_export.db")); const CString g_sqlTable = _T("create table 'AEC_ENTITIES' (\n")\ _T("'ID' integer primary key autoincrement not null,\n")\ _T("'CLASS' text not null,\n")\ _T("'SELF' integer not null,\n")\ _T("'OWNER' integer not null,\n")\ _T("'DATA' text not null);\n"); struct SimpleInterface { AcDbObjectId pid; AcGePoint3d ptPos; SimpleInterface() {}; SimpleInterface(const AcDbObjectId &id, const AcGePoint3d &pt): pid(id), ptPos(pt) {}; bool operator < (SimpleInterface s1) const { return pid < s1.pid; } }; bool isSameInterface(const AecInterface &inf1, const AecInterface &inf2) { if (EQUAL_ZERO(inf1.ptPos.distanceTo(inf2.ptPos))) return true; AcGeVector3d vt1(inf1.vtDir), vt2(inf2.vtDir); if (vt1.normalize().negate() == vt2.normalize()) { if (inf1.ptPos.distanceTo(inf2.ptPos) < (inf1.dSize1 + inf2.dSize1) * .5) return true; } return false; } // 得到 实体 接口 bool getInterfaces(AcDbObjectId id, AcArray &ar) { OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbEwPipe, pEnt) if (pEnt) { pEnt->GetInterface(ar); } OPENOBJ_END() OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbEwEquipment, pEnt) if (pEnt) { pEnt->GetInterface(ar); } OPENOBJ_END() OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbEwFitting, pEnt) if (pEnt) { pEnt->GetInterface(ar); } OPENOBJ_END() OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbECableTray, pEnt) if (pEnt) { pEnt->GetInterface(ar); } OPENOBJ_END() OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbHvacDuct, pEnt) if (pEnt) { pEnt->GetInterface(ar); } OPENOBJ_END() OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbEcFitting, pEnt) if (pEnt) { pEnt->GetInterface(ar); } OPENOBJ_END() OPENOBJ_BEGIN(id, AcDb::kForRead, AecDbHvacFitting, pEnt) if (pEnt) { pEnt->GetInterface(ar); } OPENOBJ_END() return !ar.isEmpty(); } int getMEPType(AcDbObjectId id) { if (ENT2DB::isEntity(id) ||ENT2DB::isEntity(id)) return 0; else if (ENT2DB::isEntity(id) ||ENT2DB::isEntity(id)) return 1; else if (ENT2DB::isEntity(id) ||ENT2DB::isEntity(id)) return 2; else if (ENT2DB::isEntity(id)) { AcArray ar; getInterfaces(id, ar); if (ar.isEmpty()) return -1; AecInterface &inf = ar.first(); if (inf.nType == 0) return 0; else if (inf.nType == 1) return 1; return 2; } return -1; } // 判断接口 inf 是否已经被实体记录 // 如果被记录,反回true bool hasRecord(AecInterface inf , AcDbObjectId id , const std::multimap &ss) { typedef std::multimap::const_iterator _IT; std::pair<_IT, _IT> pr = ss.equal_range(id); for (_IT it = pr.first; it != pr.second; ++it) { if (it->second.ptPos == inf.ptPos) return true; } return false; } // 判断 id1 和 id2 有没有相连的接口 // 如果找到,将关联信息写到两个实体中 // 找到返回true void findInterface(AcDbObjectId id1 , AcDbObjectId id2 , std::multimap &ss) { AcArray ar1(0), ar2(0); if (!getInterfaces(id1, ar1)) return; if (!getInterfaces(id2, ar2)) return; int nType1(-1), nType2(-1); for (int i = 0; i < ar1.length(); ++i) { AecInterface &inf1 = ar1[i]; if (hasRecord(inf1, id1, ss)) continue; nType1 = getMEPType(id1); for (int j = 0; j < ar2.length(); ++j) { AecInterface &inf2 = ar2[j]; if (hasRecord(inf2, id2, ss)) continue; nType2 = getMEPType(id2); if (isSameInterface(inf1, inf2)) { AecInterface inf = inf1; inf.nType = nType1; inf.idOwner = id2; // 在这里 idOwner 代表所连接的实体ID ss.insert(std::make_pair(id1, inf)); inf = inf2; inf.nType = nType2; inf.idOwner = id1; ss.insert(std::make_pair(id2, inf)); } } } } // 收集 管道,管件,管道附件 的接口信息 void collectInterfaceInfo(AcDbObjectIdArray ar , std::multimap &ss) { for (int i = 0; i < ar.length(); ++i) { // id 与 其它实体都比较一次 for (int j = i + 1; j < ar.length(); ++j) { findInterface(ar[i], ar[j], ss); } } // 以上代码可以处理互相连接的接口,但是没有连接的接口也需要记录。 AcArray infs(0); AecInterface inf; for (int i = 0; i < ar.length(); ++i) { infs.removeAll(); getInterfaces(ar[i], infs); if (infs.isEmpty()) continue; typedef std::multimap::const_iterator _IT; std::pair<_IT, _IT> pr = ss.equal_range(ar[i]); // 如果不在 pr 范围内存在,则说明是空接口,需要记录 int count = (int)std::distance(pr.first, pr.second); // 如果查找出记录的数量与实体本身的数量一致,说明都记录上了 if (count == infs.length()) continue; for (int j = 0; j < infs.length(); ++j) { bool isHas(false); for (_IT it = pr.first; it != pr.second; ++it) { if (isSameInterface(it->second, infs[j])) { isHas = true; break; } } if (!isHas) { inf = infs[j]; inf.idOwner = AcDbObjectId::kNull; inf.nType = getMEPType(ar[i]); ss.insert(std::make_pair(ar[i], inf)); } } } } template void getConnectorForFitting(AcDbObjectId fitID , AcDbObjectIdArray pipes , std::set &connectors) { AcArray aifs; AecInterface aif; SimpleInterface sinf; OPENOBJ_BEGIN(fitID, AcDb::kForRead, Fi, pFit) { if (!pFit) return; for (int f = 0; f < pFit->GetInterfaceCount(); ++f) { if (!pFit->GetInterface(f, aif)) continue; for (int i = 0; i < pipes.length(); ++i) { OPENOBJ_BEGIN(pipes[i], AcDb::kForRead, Pi, pPipe) { aifs.removeAll(); if (!pPipe) continue; if (!pPipe->GetInterface(aifs)) continue; if (aifs.length() < 2) continue; if (isSameInterface(aifs[0], aif)) { sinf.pid = pPipe->objectId(); sinf.ptPos = aifs[0].ptPos; connectors.insert(sinf); break; } else if (isSameInterface(aifs[1], aif)) { sinf.pid = pPipe->objectId(); sinf.ptPos = aifs[1].ptPos; connectors.insert(sinf); break; } } OPENOBJ_END() } } } OPENOBJ_END() } template void writeConnector2Fitting(AcDbObjectIdArray fids, AcDbObjectIdArray pids) { std::set connectors; CString sName(_T("")); for (int i = 0; i < fids.length(); ++i) { connectors.clear(); getConnectorForFitting(fids[i], pids, connectors); OPENOBJ_BEGIN(fids[i], AcDb::kForWrite, Fi, pFit) { AecDbObjXDataMap *pMap = pFit->GetSpecialtyData(AcDb::kForWrite); if (!pMap) continue; if (ENT2DB::isEntity(pFit)) pMap->SetAt(_T("MEP_TYPE"), 0); else if (ENT2DB::isEntity(pFit)) pMap->SetAt(_T("MEP_TYPE"), 1); else if (ENT2DB::isEntity(pFit)) pMap->SetAt(_T("MEP_TYPE"), 2); pMap->SetAt(_T("CONNECTOR_COUNT"), (int)connectors.size()); int idx(0); for (std::set::const_iterator it = connectors.begin() ; it != connectors.end() ; ++it, ++idx) { sName.Format(_T("CONNECTOR_Id_%d"), idx); pMap->SetAt(sName, it->pid); sName.Format(_T("CONNECTOR_Pos_%d"), idx); pMap->SetAt(sName, it->ptPos); } } OPENOBJ_END() } } bool getSHObjects(LPCTSTR dxf , AcDbObjectIdArray &ids , AcDbObjectIdArray &idsRepeat , std::multimap &infs) { resbuf *pRb = acutBuildList(RTDXF0, dxf, 0); ads_name ss, ent; if (CKTCadUtility::SelectEntities(_T("\n请选择要导出的上华实体:"), ss, pRb) != RTNORM) return false; //int nRes = acedSSGet(_T("A"), NULL, NULL, pRb, ss); acutRelRb(pRb); AcDbObjectId id; Adesk::Int32 lLen(0L); acedSSLength(ss, &lLen); ids.removeAll(); AcDbObjectIdArray arPipes, arDucts, arCabletray , arEwFits, arHvacFits, arEcFits, arEquis, allEw, allEc, allHv; for (long i = 0; i < lLen; ++i) { if (acedSSName(ss, i, ent) != RTNORM) continue; if (acdbGetObjectId(id, ent) != Acad::eOk) continue; OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pEnt) { if (pEnt) { // 把在revit中可以做族文件的实体都挑出来 if (AecDbXOpening::cast(pEnt) || AecDbHolder::cast(pEnt) || AecDbHanger::cast(pEnt) || AecDbBossHolder::cast(pEnt) || AecDbClimbStair::cast(pEnt) || AecDbZLineStair::cast(pEnt) || AecDbMRPLineStair::cast(pEnt) || AecDbXEquipment::cast(pEnt) || AecDbCornerStair::cast(pEnt) || AecDbCrossStair::cast(pEnt) || AecDbDoubleMulStair::cast(pEnt) || AecDbLineSegStair::cast(pEnt) || AecDbParaLlelStair::cast(pEnt) || AecDbRectCornerStair::cast(pEnt) || AecDbScissorsStair::cast(pEnt) || AecDbTriangleStair::cast(pEnt) ) idsRepeat.append(id); else ids.append(id); // 找出所有的 管实体(管线,风管,桥架)及 管件实体(管件,风管件,电气管件) if (AecDbEwPipe::cast(pEnt)) arPipes.append(id); else if (AecDbECableTray::cast(pEnt)) arCabletray.append(id); else if (AecDbHvacDuct::cast(pEnt)) arDucts.append(id); else if (AecDbEwFitting::cast(pEnt)) arEwFits.append(id); else if (AecDbEcFitting::cast(pEnt)) arEcFits.append(id); else if (AecDbHvacFitting::cast(pEnt)) arHvacFits.append(id); else if (AecDbEwEquipment::cast(pEnt)) arEquis.append(id); } } OPENOBJ_END() } acedSSFree(ss); allEw.append(arPipes); allEw.append(arEwFits); allEc.append(arCabletray); allEc.append(arEcFits); allHv.append(arDucts); allHv.append(arHvacFits); // 设备可能对应着 风管,桥架,管道,所以都放进去 allEw.append(arEquis); allHv.append(arEquis); allEc.append(arEquis); collectInterfaceInfo(allEw, infs); collectInterfaceInfo(allEc, infs); collectInterfaceInfo(allHv, infs); return !(ids.isEmpty() && idsRepeat.isEmpty()); } CString getTableName(const AcDbEntity *pEnt) { return _T("AEC_ENTITIES"); const AecDbXWall *pWall(AecDbXWall::cast(pEnt)); if (pWall) return _T("AEC_WALL"); const AecDbBeam *pBeam(AecDbBeam::cast(pEnt)); if (pBeam) return _T("AEC_BEAM"); const AecDbXSlab *pSlab(AecDbXSlab::cast(pEnt)); if (pSlab) return _T("AEC_SLAB"); const AecDbColumn *pColumn(AecDbColumn::cast(pEnt)); if (pColumn) return _T("AEC_COLUMN"); const AecDbEwEquipment *pEqu(AecDbEwEquipment::cast(pEnt)); if (pEqu) return _T("AEC_EQU"); const AecDbParamEquipment *pParamEqu(AecDbParamEquipment::cast(pEnt)); if (pParamEqu) return _T("AEC_PARAMEQU"); const AecDbFlume *pFlume(AecDbFlume::cast(pEnt)); if (pFlume) return _T("AEC_FLUME"); const AecDbRiverGroove *pGroove(AecDbRiverGroove::cast(pEnt)); if (pGroove) return _T("AEC_GROOVE"); const AecDbEwPipe *pPipe(AecDbEwPipe::cast(pEnt)); if (pPipe) return _T("AEC_PIPE"); const AecDbX3dPartEntity *p3d(AecDbX3dPartEntity::cast(pEnt)); if (p3d) return _T("AEC_X3DPART"); return _T(""); } CString getUniqueName(AcDbObjectId id) { CString str(_T("")); OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pEnt) { if (pEnt) { AecDbEntityBase *pBase(AecDbEntityBase::cast(pEnt)); AecDbCurveBase *pCurve(AecDbCurveBase::cast(pEnt)); if (pBase) return pBase->getUniqueName(); if (pCurve) return pCurve->getUniqueName(); } } OPENOBJ_END() return str; } bool _export(TSQLite &dbSql, const WValue &v, LPCTSTR pszTable, WValue &debug) { if (!pszTable) return false; WValue vClone; vClone.CopyFrom(v, getJsonAllocator()); CString sql(_T("")); std::wstring self, owner; MCIt itSelf = v.FindMember(_T("__self__")); MCIt itOwner = v.FindMember(_T("__owner__")); MCIt itClass = v.FindMember(_T("__class__")); Adesk::IntDbId idSelf(0), idOwner(0); CString sClass(_T("")); if (itSelf != v.MemberEnd()) idSelf = itSelf->value.GetInt64(); if (itOwner != v.MemberEnd()) idOwner = itOwner->value.GetInt64(); if (itClass != v.MemberEnd()) sClass = itClass->value.GetString(); self = TypeConvert::convert(idSelf); owner = TypeConvert::convert(idOwner); sql.Format(_T("insert into %s ('CLASS','SELF','OWNER','DATA') values('%s','%s','%s','%s')") , pszTable , sClass , self.c_str() , owner.c_str() , write2Json(v).c_str()); if (!dbSql.exec(sql)) return false; #ifndef NDEBUG if (!debug.IsNull()) { pushBack(debug, vClone); } #endif return true; } void Export(TSQLite &dbSql , AcDbObjectIdArray &ar , const AcDbObjectIdArray &arRepeat , const std::multimap &infs , WValue &jsonFile) { /* 实体的 ToJson()函数返回的 json 结构必须有 __self__,__owner__,两个字段 如果存在 __attachment__ 结构,则说明存在附着体(目前只有 构筑物上的单体) { "__self__": AcDbObjectId.asOldId(), 必有 "__owner__": AcDbObjectId.asOldId(), 必有 "__xdata__": 实体的AecDbObjXDataMap, 可选 "__attachment__":{} 可选 } */ if (ar.isEmpty() && arRepeat.isEmpty()) return; // 处理一下重复实体 std::map mmRepeats; std::map mmIds; // 保存了绘制几何信息的实体的id CString name; AcDbObjectIdArray arids; AcDbObjectId idRepeat; for (int i(0); i < arRepeat.length(); ++i) { idRepeat = arRepeat[i]; name = getUniqueName(idRepeat); if (name.IsEmpty()) { // 没有直接放到ar里面处理 ar.append(idRepeat); continue; } else { // 判断名字在不在mm里面 std::map::iterator it(mmRepeats.end()); it = mmRepeats.find(name); if (it == mmRepeats.end()) // 不在 { arids.removeAll(); arids.append(idRepeat); mmRepeats.insert(std::make_pair(name, arids)); // idRepeat 是 这个重复实体中得第一个,放到ar里面处理 ar.append(idRepeat); mmIds.insert(std::make_pair(name, idRepeat.asOldId())); } else { it->second.append(idRepeat); } } } AcDbObjectId id; WValue v; CString table(_T("")), uniqueName(_T("")); for (int i = 0; i < ar.length(); ++i) { v.SetNull(); id = ar[i]; OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pEnt) { if (!pEnt) continue; table = getTableName(pEnt); if (table.IsEmpty()) continue; AecDbEntityBase *pBase(AecDbEntityBase::cast(pEnt)); AecDbCurveBase *pCurve(AecDbCurveBase::cast(pEnt)); if (pBase) { v.Swap(pBase->ToJson(true)); uniqueName = pBase->getUniqueName(); } else if (pCurve) { v.Swap(pCurve->ToJson(true)); uniqueName = pCurve->getUniqueName(); } else continue; addMember(v, _T("_unique_name_"), uniqueName); // 处理一下接口,为v加入接口信息 typedef std::multimap::const_iterator _IT; std::pair<_IT, _IT> pr = infs.equal_range(id); if (pr.first != infs.end()) { WValue jArInf; jArInf.SetArray(); for (_IT it = pr.first; it != pr.second; ++it) { WValue jInf; jInf.SetObject(); addMember(jInf, _T("__ptPos__"), GEO2JSON::point(it->second.ptPos).ToJson()); addMember(jInf, _T("__vtDir__"), GEO2JSON::vector(it->second.vtDir).ToJson()); addMember(jInf, _T("__dSize1__"), it->second.dSize1); addMember(jInf, _T("__dSize2__"), it->second.dSize2); addMember(jInf, _T("__nSectType__"), (int)it->second.nSectType); addMember(jInf, _T("__idConnect__"), it->second.idOwner.asOldId()); addMember(jInf, _T("__nMEPType__"), (int)it->second.nType); pushBack(jArInf, jInf); } addMember(v, _T("__interfaces__"), jArInf); } } OPENOBJ_END() if (!_export(dbSql, v, table, jsonFile)) continue; } std::map::const_iterator it(mmRepeats.begin()); for (; it != mmRepeats.end(); ++it) { // 每种类型得第一个都在 ar 里面处理了 for (int i(1); i < it->second.length(); ++i) { v.SetNull(); id = it->second[i]; OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pEnt) { if (!pEnt) continue; table = getTableName(pEnt); if (table.IsEmpty()) continue; AecDbEntityBase *pBase(AecDbEntityBase::cast(pEnt)); AecDbCurveBase *pCurve(AecDbCurveBase::cast(pEnt)); if (pBase) { v.Swap(pBase->ToJson(false)); uniqueName = pBase->getUniqueName(); } else if (pCurve) { v.Swap(pCurve->ToJson(false)); uniqueName = pCurve->getUniqueName(); } else continue; addMember(v, _T("_unique_name_"), uniqueName); // 通过 uniqueName 找到 有几何信息的实体id std::map::const_iterator _it = mmIds.find(uniqueName); if (_it != mmIds.end()) { addMember(v, _T("_geo_ent_id_"), _it->second); } } OPENOBJ_END() if (!_export(dbSql, v, table, jsonFile)) continue; } } } void export2Db() { CFileDialog dlg(FALSE, _T("*.she"), NULL, OFN_HIDEREADONLY, _T("导出数据 (*.she)|*.she||"), acedGetAcadFrame()); if (dlg.DoModal() != IDOK) return; CString dbPath = dlg.GetPathName(); CString jsonPath = dbPath; jsonPath.Replace(_T(".she"), _T(".json")); CString dbFile = FilePath::GetSysDir() + g_dbName; if (_taccess(dbFile, 0x0) != 0x0) { AfxMessageBox(_T("未找到导出模板!")); return; } if (!::CopyFile(dbFile, dbPath, FALSE)) { AfxMessageBox(_T("复制模板文件失败!")); return; } TSQLite dbSql; if (!dbSql.open(dbPath)) { AfxMessageBox(_T("打开数据库失败!")); return; } if (!dbSql.exec(g_sqlTable)) { AfxMessageBox(_T("初始化表格失败!")); return; } AcDbObjectIdArray ids, idsRepeat; CString psz(_T("AEC_DBWALL")\ _T(",AEC_DBBEAM")\ _T(",AEC_DBSLAB")\ _T(",AEC_DBCOLMN")\ _T(",AEC_DBWEQUIPMENT")\ _T(",AEC_DBPARAEQUI")\ _T(",AEC_DBFLUME")\ _T(",AEC_RIVERGROOVE")\ _T(",AEC_EWPIPE")\ _T(",AEC_DBEWFIT")\ _T(",AEC_GUARDBAR")\ _T(",AEC_DBLSTAIR")\ _T(",AEC_DBASTAIR")\ _T(",AEC_CLMSTAIR")\ _T(",AEC_DBHVACFIT")\ _T(",AEC_DBECFIT")\ _T(",AEC_DBCABTRY")\ _T(",AEC_DBDUCT")\ _T(",AEC_MULTIPARTENT")\ _T(",AEC_DBWEIR")\ _T(",AEC_DBEXTENDENT")\ _T(",AEC_DBXEQUIPMENT")\ _T(",AEC_DBOPENING")\ _T(",AEC_DBEWPIPEBASE")\ _T(",AEC_DBMRPSTAIR")\ _T(",AEC_DBZSTAIR")\ _T(",AEC_DBXROOF")\ _T(",AEC_DBBOSSHOLDER")\ _T(",AEC_DBHANGER")\ _T(",AEC_DBHOLDER")\ _T(",AEC_EWCABLE")\ _T(",AEC_DBCNRSTAIR")\ _T(",AEC_CROSSSTAIR")\ _T(",AEC_DOUBLEMULSTAIR")\ _T(",AEC_DBLNSTAIR")\ _T(",AEC_PARALLELSTAIR")\ _T(",AEC_RECTCORNERSTAIR")\ _T(",AEC_SCISSORSSTAIR")\ _T(",AEC_TRIANGLESTAIR")\ _T(",AEC_X3DPART")); WValue jsonFile; #ifndef NDEBUG jsonFile.SetArray(); // 此版本后(包括版本2),所有自定义设备(包括revit导入),全部由代码生成,不需要额外rfa文件 WValue ver; SHJson::addMember(ver, _T("_version_"), 2); SHJson::pushBack(jsonFile, ver); #endif std::multimap ss; if (getSHObjects(psz, ids, idsRepeat, ss)) { dbSql.beginTrans(); // 放入版本 CString sql; sql.Format(_T("insert into AEC_ENTITIES ('CLASS','SELF','OWNER','DATA') values('_version_','0','0','2')")); dbSql.exec(sql); Export(dbSql, ids, idsRepeat, ss, jsonFile); dbSql.commitTrans(); } #ifndef NDEBUG if (!jsonFile.IsNull()) { SHJson::json2File(jsonPath, jsonFile, true); } #endif } void extractSection() { AcDbObjectIdArray ids; CString psz(_T("AEC_DBWALL")\ _T(",AEC_DBBEAM")\ _T(",AEC_DBSLAB")\ _T(",AEC_DBCOLMN")); resbuf *pRb = acutBuildList(RTDXF0, psz, 0); ads_name ss, ent; if (CKTCadUtility::SelectEntities(_T("\n请选择要导出的上华实体:"), ss, pRb) != RTNORM) return; acutRelRb(pRb); AcDbObjectId id; Adesk::Int32 lLen(0L); acedSSLength(ss, &lLen); ids.removeAll(); for (long i = 0; i < lLen; ++i) { if (acedSSName(ss, i, ent) != RTNORM) continue; if (acdbGetObjectId(id, ent) != Acad::eOk) continue; ids.append(id); } acedSSFree(ss); WValue ar, v; ar.SetArray(); for (int i = 0; i < ids.length(); ++i) { OPENOBJ_BEGIN(ids[i], AcDb::kForRead, AecDbBDPipeBase, pEnt) { if (!pEnt) continue; v.SetObject(); AcDbRegion *pReg = pEnt->GetSection(); AcDbCurve *pCurve = pEnt->GetBaseCurve(); if (pReg) { SHJson::addMember(v, _T("section"), GEO2JSON::region(*pReg).ToJson()); CoreTools::CloneAndAddToModelSpace(pReg); DELETE_PTR(pReg); } if (pCurve) { SHJson::addMember(v, _T("path"), GEO2JSON::region(*pCurve).ToJson()); CoreTools::CloneAndAddToModelSpace(pCurve); DELETE_PTR(pCurve); } SHJson::pushBack(ar, v); } OPENOBJ_END() } //SHJson::json2File(jsonPath, ar, true); } } namespace { void polygon_boolean(const int &type , const AcDbPolyline *p1 , const AcDbPolyline *p2 , AcDbPolyline &pRes) { } }