基于VC++和ObjectARX开发的AutoCAD曲线交点打断功能实现代码

// 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;
}

调试与优化建议

  1. 几何精度控制

    #define GEOMETRY_TOLERANCE 1e-6
    AcGeTol geTol;
    geTol.setAbsolute(GEOMETRY_TOLERANCE);
    
  2. 性能监控

    clock_t start = clock();
    // 执行计算
    clock_t end = clock();
    double duration = (double)(end - start)/CLOCKS_PER_SEC;
    acutPrintf(_T("\n处理时间: %.3f秒"), duration);
    
  3. 异常处理

    try {
        // 关键操作
    }
    catch (const AcRxException& e) {
        acutPrintf(_T("\n错误: %s"), e.message());
    }
    

部署与使用说明

  1. 编译配置 使用VC++ 2019及以上版本 链接ObjectARX 2025库 包含AutoCAD头文件路径

  2. 加载方法

    (command "-LISPLOAD" "CurveBreaker.arx")
    
  3. 命令调用

    BREAKINT
    

参考代码 VC+ObjectARX开发的AutoCad中的曲线选择集交点打断源码 www.youwenfan.com/contentcnk/72294.html

典型应用场景

  1. 管道网络优化 自动识别管线交叉点 生成节点连接图
  2. 电路设计 处理导线交叉 生成连接点标记
  3. 建筑结构分析 识别梁柱交点 自动生成节点详图
posted @ 2025-10-30 10:05  kiyte  阅读(12)  评论(0)    收藏  举报