#include "KTCad.h" #include "dwg_annotate_common.h" #include "dbcolor.h" // AcCmColor #include #include // windows.h(经 afxwin.h)把 min/max 定义成宏,会顶掉下面的 std::min / std::max // (CadProject 那边的 cadsdk.h 里带了 NOMINMAX,本仓库的 KTCad.h 没有)。 #undef min #undef max namespace dwg_annotate { DocLock::DocLock() : m_bLocked(false), m_pDoc(NULL) { m_pDoc = acDocManager->curDocument(); if (m_pDoc != NULL && acDocManager->lockDocument(m_pDoc) == Acad::eOk) m_bLocked = true; } DocLock::~DocLock() { if (m_bLocked && m_pDoc != NULL) acDocManager->unlockDocument(m_pDoc); } using namespace dwg_review; const char* kDefaultAnnotLayer = "AI_REVIEW"; // =========================================================================== // 编码 // =========================================================================== std::wstring utf8ToWStr(const std::string& s) { if (s.empty()) return std::wstring(); int len = ::MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), NULL, 0); if (len <= 0) return std::wstring(); std::wstring out((size_t)len, L'\0'); ::MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), &out[0], len); return out; } // =========================================================================== // 图层 // =========================================================================== bool ensureLayer(AcDbDatabase* pDb, const std::string& name, int aciColor) { if (!pDb || name.empty()) return false; const std::wstring wn = utf8ToWStr(name); // 已存在则直接返回 AcDbLayerTable* pLT = nullptr; if (pDb->getLayerTable(pLT, AcDb::kForRead) == Acad::eOk && pLT) { const bool exists = pLT->has(wn.c_str()); pLT->close(); if (exists) return true; } // 创建新图层 if (pDb->getLayerTable(pLT, AcDb::kForWrite) != Acad::eOk || !pLT) return false; AcDbLayerTableRecord* pRec = new AcDbLayerTableRecord(); pRec->setName(wn.c_str()); AcCmColor color; color.setColorIndex((Adesk::UInt16)aciColor); pRec->setColor(color); const Acad::ErrorStatus es = pLT->add(pRec); pRec->close(); pLT->close(); return es == Acad::eOk || es == Acad::eDuplicateRecordName; } // =========================================================================== // 空间 // =========================================================================== AcDbBlockTableRecord* openWriteSpace(AcDbDatabase* pDb, const std::string& space) { if (!pDb) return nullptr; AcDbBlockTable* pBT = nullptr; if (pDb->getBlockTable(pBT, AcDb::kForRead) != Acad::eOk || !pBT) return nullptr; AcDbBlockTableRecord* pRec = nullptr; if (space.empty() || space == "Model" || space == "model") { pBT->getAt(ACDB_MODEL_SPACE, pRec, AcDb::kForWrite); } else { AcDbObjectId id; const std::wstring ws = utf8ToWStr(space); if (pBT->getAt(ws.c_str(), id) == Acad::eOk) acdbOpenObject(pRec, id, AcDb::kForWrite); } pBT->close(); return pRec; } // =========================================================================== // 参数解析 // =========================================================================== bool parsePoint(const nlohmann::json& j, AcGePoint3d& out) { if (j.is_array() && j.size() >= 2) { out.x = j[0].get(); out.y = j[1].get(); out.z = (j.size() >= 3) ? j[2].get() : 0.0; return true; } if (j.is_object() && j.contains("x") && j.contains("y")) { out.x = j["x"].get(); out.y = j["y"].get(); out.z = j.contains("z") ? j["z"].get() : 0.0; return true; } return false; } bool parsePoints(const nlohmann::json& arr, std::vector& out) { out.clear(); if (!arr.is_array()) return false; for (size_t i = 0; i < arr.size(); ++i) { AcGePoint3d p; if (!parsePoint(arr[i], p)) { out.clear(); return false; } out.push_back(p); } return !out.empty(); } bool parseWindow(const nlohmann::json& args, double& x1, double& y1, double& x2, double& y2) { if (args.contains("window") && args["window"].is_object()) { const nlohmann::json& w = args["window"]; if (w.contains("min_x") && w.contains("min_y") && w.contains("max_x") && w.contains("max_y")) { x1 = w["min_x"].get(); y1 = w["min_y"].get(); x2 = w["max_x"].get(); y2 = w["max_y"].get(); return true; } } if (args.contains("min_x") && args.contains("min_y") && args.contains("max_x") && args.contains("max_y")) { x1 = args["min_x"].get(); y1 = args["min_y"].get(); x2 = args["max_x"].get(); y2 = args["max_y"].get(); return true; } if (args.contains("p1") && args.contains("p2")) { AcGePoint3d a, b; if (parsePoint(args["p1"], a) && parsePoint(args["p2"], b)) { x1 = (std::min)(a.x, b.x); y1 = (std::min)(a.y, b.y); x2 = (std::max)(a.x, b.x); y2 = (std::max)(a.y, b.y); return true; } } return false; } std::vector collectHandlesArg(const nlohmann::json& args) { std::vector hs; if (args.contains("handle") && args["handle"].is_string()) hs.push_back(args["handle"].get()); if (args.contains("handles") && args["handles"].is_array()) { for (size_t i = 0; i < args["handles"].size(); ++i) if (args["handles"][i].is_string()) hs.push_back(args["handles"][i].get()); } return hs; } // =========================================================================== // 公共参数默认值 // =========================================================================== std::string getLayerArg(const nlohmann::json& args) { if (args.contains("layer") && args["layer"].is_string()) return args["layer"].get(); return std::string(kDefaultAnnotLayer); } int getColorArg(const nlohmann::json& args, int def) { if (args.contains("color") && args["color"].is_number_integer()) return args["color"].get(); return def; } std::string getSpaceArg(const nlohmann::json& args) { if (args.contains("space") && args["space"].is_string()) return args["space"].get(); return std::string("Model"); } // =========================================================================== // 实体写入 // =========================================================================== void applyLayerColor(AcDbEntity* pEnt, const std::string& layer, int aciColor) { if (!pEnt) return; if (!layer.empty()) { const std::wstring wl = utf8ToWStr(layer); pEnt->setLayer(wl.c_str()); } pEnt->setColorIndex((Adesk::UInt16)aciColor); } AcDbObjectId appendToSpace(AcDbBlockTableRecord* pSpace, AcDbEntity* pEnt) { AcDbObjectId id = AcDbObjectId::kNull; if (!pEnt) return id; if (!pSpace) { pEnt->close(); return id; } if (pSpace->appendAcDbEntity(id, pEnt) != Acad::eOk) id = AcDbObjectId::kNull; pEnt->close(); return id; } std::string handleOfId(AcDbDatabase* pDb, const AcDbObjectId& id) { if (!pDb || id == AcDbObjectId::kNull) return std::string(); AcDbEntity* pEnt = nullptr; if (acdbOpenObject(pEnt, id, AcDb::kForRead) != Acad::eOk || !pEnt) return std::string(); const std::string h = handleOf(pEnt); pEnt->close(); return h; } // =========================================================================== // 结果构造 // =========================================================================== nlohmann::json makeCreatedItem(AcDbDatabase* pDb, const AcDbObjectId& id, const std::string& type, const std::string& layer) { nlohmann::json item; item["handle"] = handleOfId(pDb, id); item["type"] = type; item["layer"] = layer; return item; } nlohmann::json createdResult(const std::vector& created) { nlohmann::json r; r["ok"] = true; r["count"] = (int)created.size(); r["created"] = created; return makeJsonResult(r); } } // namespace dwg_annotate