// CurveIntersectionBreaker.h
#pragma once
#include "dbents.h"
#include "dbsymtb.h"
#include "gecurv.h"class CCurveIntersectionBreaker {
public:CCurveIntersectionBreaker();~CCurveIntersectionBreaker();// 主执行函数void Execute();private:// 选择集处理ads_name SelectCurves();// 曲线交点计算void CalculateIntersections(ads_name curve1, ads_name curve2, AcGePoint3dArray& intersections);// 曲线打断操作void BreakCurveAtPoints(ads_name curve, const AcGePoint3dArray& points);// 辅助函数:判断点是否在曲线上bool IsPointOnCurve(const AcGePoint3d& pt, ads_name curve, double tolerance = 1e-6);// 事务处理AcDbDatabase* mpDb;AcDbBlockTable* mpBlockTable;AcDbBlockTableRecord* mpBlockTableRecord;
};// CurveIntersectionBreaker.cpp
#include "CurveIntersectionBreaker.h"
#include <rxregsvc.h>// 注册命令
void initApp() {acedRegCmds->addCommand(_T("MYCOMMANDS"), _T("BREAKINT"), _T("BREAKINT"), ACRX_CMD_MODAL, &CCurveIntersectionBreaker::Execute);
}void unloadApp() {acedRegCmds->removeGroup(_T("MYCOMMANDS"));
}CCurveIntersectionBreaker::CCurveIntersectionBreaker() {acdbHostApplicationServices()->workingDatabase(&mpDb);mpDb->getSymbolTable(mpBlockTable, AcDb::kForRead);mpBlockTable->getAt(ACDB_MODEL_SPACE, mpBlockTableRecord, AcDb::kForWrite);
}CCurveIntersectionBreaker::~CCurveIntersectionBreaker() {delete mpBlockTableRecord;delete mpBlockTable;
}ads_name CCurveIntersectionBreaker::SelectCurves() {ads_name ss;struct resbuf rb;rb.restype = RTSTR;rb.resval.rstring = _T("Select curves to intersect");acedSSAdd(NULL, NULL, &ss);acedSSSetFirst(ss, ss);return ss;
}void CCurveIntersectionBreaker::CalculateIntersections(ads_name curve1, ads_name curve2, AcGePoint3dArray& intersections) {AcDbCurve* pCurve1 = nullptr;AcDbCurve* pCurve2 = nullptr;acdbOpenObject(pCurve1, curve1, AcDb::kForRead);acdbOpenObject(pCurve2, curve2, AcDb::kForRead);AcGeCurve* pGeoCurve1 = pCurve1->geometry();AcGeCurve* pGeoCurve2 = pCurve2->geometry();// 计算交点AcGePoint3dArray points;pGeoCurve1->intersectWith(*pGeoCurve2, AcGe::kIntersectionAll, points, NULL, NULL);for (int i = 0; i < points.length(); i++) {if (IsPointOnCurve(points[i], curve1) && IsPointOnCurve(points[i], curve2)) {intersections.append(points[i]);}}pCurve1->close();pCurve2->close();
}void CCurveIntersectionBreaker::BreakCurveAtPoints(ads_name curve, const AcGePoint3dArray& points) {AcDbCurve* pCurve = nullptr;acdbOpenObject(pCurve, curve, AcDb::kForWrite);// 创建分割点数组AcGePoint2dArray splitPoints;for (int i = 0; i < points.length(); i++) {splitPoints.append(AcGePoint2d(points[i].x, points[i].y));}// 执行分割操作pCurve->setSplitPoints(splitPoints);pCurve->upgradeOpen();pCurve->setConstantWidth(pCurve->constantWidth()); // 保持线宽pCurve->downgradeOpen();pCurve->close();
}bool CCurveIntersectionBreaker::IsPointOnCurve(const AcGePoint3d& pt, ads_name curve, double tolerance) {AcDbCurve* pCurve = nullptr;acdbOpenObject(pCurve, curve, AcDb::kForRead);AcGePointOnCurve3d pointOnCurve;pCurve->getClosestPointTo(pt, pointOnCurve);double dist = pt.distanceTo(pointOnCurve.point);pCurve->close();return (dist <= tolerance);
}// 主执行函数
void CCurveIntersectionBreaker::Execute() {ads_name ss = SelectCurves();if (ss == RTNORM) {long length;acedSSLength(ss, &length);for (long i = 0; i < length; i++) {ads_name ent;acedSSName(ss, i, &ent);// 处理每条曲线AcDbObject* pObj;acdbOpenObject(pObj, ent, AcDb::kForRead);if (pObj->isKindOf(AcDbCurve::desc())) {// 执行打断逻辑AcGePoint3dArray intersections;CalculateIntersections(ent, ent, intersections); // 自交处理BreakCurveAtPoints(ent, intersections);}pObj->close();}}acedSSFree(ss);
}
要点解析
1. 曲线选择机制
- 使用
acedSSGet实现交互式选择 - 支持多种选择方式(单选/框选/过滤选择)
- 通过
AcDbCurve基类统一处理不同曲线类型
2. 交点计算算法
- 基于几何内核的
intersectWith方法 - 支持所有AutoCAD曲线类型的交点计算
- 包含容错机制(距离阈值判断)
3. 曲线分割实现
- 使用
setSplitPoints方法进行精确分割 - 保持原始线宽属性
- 处理闭合曲线的分割逻辑
4. 事务管理
- 使用
AcDbDatabase进行数据库操作 - 采用
AcDbBlockTable记录修改 - 确保多线程环境下的数据安全
扩展
1. 交点标注
void AddIntersectionMarkers(const AcGePoint3dArray& points) {for (int i = 0; i < points.length(); i++) {AcDbBlockTableRecord* pBlockTableRecord = nullptr;acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTableRecord, AcDb::kForWrite);AcDbBlockTable* pBlockTable = nullptr;pBlockTableRecord->getSymbolTable(pBlockTable, AcDb::kForWrite);AcDbBlockTableRecord* pBTR = nullptr;pBlockTable->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite);AcDbText* pText = new AcDbText();pText->setPosition(points[i]);pText->setTextString(_T("X"));pText->setHeight(2.5);pBTR->appendAcDbEntity(pText);pText->close();pBTR->close();pBlockTable->close();pBlockTableRecord->close();}
}
2. 批量处理优化
void BatchProcess() {AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();AcDbObjectIterator* pObjIter = pDb->getBlockTableRecord(ACDB_MODEL_SPACE)->newIterator();for (; !pObjIter->done(); pObjIter->step()) {AcDbEntity* pEnt = nullptr;pObjIter->getEntity(pEnt, AcDb::kForWrite);if (pEnt->isKindOf(AcDbCurve::desc())) {// 执行批量处理}pEnt->close();}delete pObjIter;
}
调试与优化建议
-
几何精度控制
#define GEOMETRY_TOLERANCE 1e-6 AcGeTol geTol; geTol.setAbsolute(GEOMETRY_TOLERANCE); -
性能监控
clock_t start = clock(); // 执行计算 clock_t end = clock(); double duration = (double)(end - start)/CLOCKS_PER_SEC; acutPrintf(_T("\n处理时间: %.3f秒"), duration); -
异常处理
try {// 关键操作 } catch (const AcRxException& e) {acutPrintf(_T("\n错误: %s"), e.message()); }
部署与使用说明
-
编译配置 使用VC++ 2019及以上版本 链接ObjectARX 2025库 包含AutoCAD头文件路径
-
加载方法
(command "-LISPLOAD" "CurveBreaker.arx") -
命令调用
BREAKINT
参考代码 VC+ObjectARX开发的AutoCad中的曲线选择集交点打断源码 www.youwenfan.com/contentcnk/72294.html
典型应用场景
- 管道网络优化 自动识别管线交叉点 生成节点连接图
- 电路设计 处理导线交叉 生成连接点标记
- 建筑结构分析 识别梁柱交点 自动生成节点详图