用MarsCode开发CAD插件功能


先来说说这段时间用AI写代码的初步感受

在过去的几天里,尝试了多款AI代码生成工具,包括Cursor、豆包MarsCode、
通义灵码TongYi、文心快码BaiduComate以及腾讯AI助手。通过对这些工具的
使用体验进行比较,我发现Cursor在代码完整度、可用性、代码质量以及界面
交互方面表现尤为出色,完胜国内其他几款AI工具。特别是在涉及到一些几何
算法库时,Cursor生成的代码几乎是唯一可用的,尽管目前还未达到理想的效果。
相比之下,国内的AI工具在处理较为复杂或语料较少的情况时,生成的回复往往
有种顾左右而言他的感觉。此外,从生成的代码来看,这些AI工具的训练数据似
乎较为陈旧,例如在OCCT库中,一些接口的变化并未被AI所了解。在生成前端
项目时,几款AI工具的表现都还不错,它们能够生成完整的框架结构,并且编译
后可以正常运行。期间曾使用Cursor生成了一个VisualLisp的语法着色插件,由
于之前对js和ts的经验较少,因此经过了几十轮对话才使其成功运行。在这个过
程中,还遇到了一个bug,导致它在两个问题上一直循环,最后不得不手动处理
才得以解决。

总的来说,AI代码生成工具在提高开发效率方面具有巨大潜力,但仍有许多改
进空间。随着技术的不断发展,相信这些工具将会变得越来越智能和实用。一旦
它们迭代成熟,估计软件开发从业人员又有大批面临再就业的困境。

Cursor+QT6.4+OCCT7.7.0+六轮对话生成的几何预览


来说说使用小技巧吧:

1. 尽可能提供详细的上下文

 "生成一个登录页面"
 "使用React和Tailwind CSS生成一个登录页面,需要包含邮箱验证和密码强度检查"

2. 分步骤请求

将复杂的需求拆分成小步骤:
- 先请求基础架构
- 再添加具体功能
- 最后优化细节

3. 使用迭代式开发

1. 生成初始版本
2. 审查代码
3. 要求具体的改进
4. 重复以上步骤

4. 明确技术要求

- 指定编程语言版本
- 说明依赖库要求
- 提供性能或兼容性要求

5. 提供示例

 "生成一个API接口"
 "按照以下格式生成一个用户注册API:
{
    'endpoint': '/api/register',
    'method': 'POST',
    'request': {
        'username': 'string',
        'email': 'string'
    }
}"

6. 使用代码审查

  • 检查生成的代码是否符合最佳实践
  • 验证错误处理
  • 确保代码安全性
  • 检查性能问题

7. 提供反馈

如果生成的代码不理想:
- 指出具体问题
- 解释期望的结果
- 要求特定的修改

以下是一个使用MarsCode生成的插件示例

没有经过测试,后面用Cursor改了提示+重新生成了部分代码+手动重写核心拓扑算法

提问:基于AutoCAD的ObjectARX二次开发接口开发一个一键剪切多段线的功能,输入参数有两个,一个被剪切对象集,一个修剪对象,被剪切对象集为N个多段线(可能是闭合,也可能是非闭合的),修剪对象为一条非闭合或闭合多段线,程序要根据修剪对象将被剪切对象切成几个部分,如果被剪切对象为闭合多段线,则将它切分成几个独立的闭合多段线,如果被剪切对象为非闭合多段线,则将其切为几个独立的非闭合多段线,然后输出所有结果。

MarsCode AI:

好的,根据你的需求,我将使用 C++ 和 ObjectARX 库来实现一键剪切多段线的功能。以下是一个简单的示例代码,它展示了如何使用 ObjectARX 库来处理 AutoCAD 中的实体对象。

cpp

#include 
#include 
#include 
#include 
#include 

void CutPolylines(AcDbObjectIdArray& cutLines, AcDbObjectId cutLineId)
{
    AcDbEntity* cutLineEnt = nullptr;
    acdbOpenObject(cutLineEnt, cutLineId, AcDb::kForRead);
    if (cutLineEnt->isKindOf(AcDbPolyline::desc()))
    {
        AcDbPolyline* cutLine = AcDbPolyline::cast(cutLineEnt);
        if (cutLine->isClosed())
        {
            // 处理闭合多段线的剪切
            for (int i = 0; i < cutlines.length i acdbentity lineent='nullptr;' acdbopenobjectlineent cutlinesi acdb::kforread if lineent->isKindOf(AcDbPolyline::desc()))
                {
                    AcDbPolyline* line = AcDbPolyline::cast(lineEnt);
                    if (line->isClosed())
                    {
                        // 闭合多段线之间的剪切,将其切分成几个独立的闭合多段线
                        // 这里需要实现具体的剪切算法
                        //...
                    }
                    else
                    {
                        // 非闭合多段线与闭合多段线的剪切,将其切为几个独立的非闭合多段线
                        // 这里需要实现具体的剪切算法
                        //...
                    }
                    lineEnt->close();
                    delete lineEnt;
                }
            }
        }
        else
        {
            // 处理非闭合多段线的剪切
            for (int i = 0; i < cutlines.length i acdbentity lineent='nullptr;' acdbopenobjectlineent cutlinesi acdb::kforread if lineent->isKindOf(AcDbPolyline::desc()))
                {
                    AcDbPolyline* line = AcDbPolyline::cast(lineEnt);
                    if (line->isClosed())
                    {
                        // 闭合多段线与非闭合多段线的剪切,将其切为几个独立的非闭合多段线
                        // 这里需要实现具体的剪切算法
                        //...
                    }
                    else
                    {
                        // 非闭合多段线之间的剪切,将其切为几个独立的非闭合多段线
                        // 这里需要实现具体的剪切算法
                        //...
                    }
                    lineEnt->close();
                    delete lineEnt;
                }
            }
        }
        cutLineEnt->close();
        delete cutLineEnt;
    }
}

void CutPolylinesCommand()
{
    AcDbObjectIdArray cutLines;
    AcDbObjectId cutLineId;

    // 获取用户选择的被剪切对象集和修剪对象
    // 这里需要实现具体的选择逻辑
    //...

    CutPolylines(cutLines, cutLineId);
}

extern "C" AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)
{
    switch (msg)
    {
    case AcRx::kInitAppMsg:
        acrxDynamicLinker->unlockApplication(pkt);
        acrxRegisterAppMDIAware(pkt);
        acutPrintf(_T("\n加载一键剪切多段线功能"));
        break;
    case AcRx::kUnloadAppMsg:
        acutPrintf(_T("\n卸载一键剪切多段线功能"));
        break;
    default:
        break;
    }
    return AcRx::kRetOK;
}

在这个示例中,CutPolylines 函数接受两个参数:一个是被剪切对象集(AcDbObjectIdArray),另一个是修剪对象(AcDbObjectId)。函数内部首先打开修剪对象,并检查它是否是一个多段线。如果是,它会进一步检查多段线是否闭合。然后,它会遍历被剪切对象集,对每个多段线进行剪切操作。剪切操作的具体实现需要根据实际需求来完成,可以使用 ObjectARX 库提供的几何操作函数来实现。

CutPolylinesCommand 函数是一个命令函数,它负责获取用户选择的被剪切对象集和修剪对象,并调用 CutPolylines 函数进行剪切操作。

acrxEntryPoint 函数是 ObjectARX 应用程序的入口点,它在应用程序加载和卸载时被调用。在这个函数中,我们注册了一个命令 CutPolylinesCommand,以便用户可以通过命令行来调用这个功能。

请注意,这个示例代码只是一个框架,你需要根据实际需求来实现具体的剪切算法和选择逻辑。

提问:Workspace // 获取用户选择的被剪切对象集和修剪对象 // 这里需要实现具体的选择逻辑 //...将这部分实现写出来

MarsCode AI:

在 ObjectARX 中,获取用户选择的对象通常涉及到与 AutoCAD 交互,以便用户可以通过图形界面选择对象。以下是一个简单的示例,展示了如何获取用户选择的被剪切对象集和修剪对象。在这个示例中,我们将使用 acedSSGet() 函数来获取用户选择的对象。

cpp

#include 
#include 
#include 
#include 
#include 

void CutPolylinesCommand()
{
    AcDbObjectIdArray cutLines;
    AcDbObjectId cutLineId;

    // 提示用户选择被剪切对象集
    acutPrintf(_T("\n请选择被剪切的多段线对象:"));
    ads_name ssname;
    if (acedSSGet(_T(""), NULL, NULL, NULL, ssname)!= RTNORM)
    {
        acutPrintf(_T("\n选择对象失败!"));
        return;
    }

    // 将选择集中的对象转换为 AcDbObjectId 数组
    long sslen;
    acedSSLength(ssname, &sslen);
    for (long i = 0; i < sslen i ads_name ename acedssnamessname i ename acdbobjectid id acdbgetobjectidid ename cutlines.appendid acutprintf_t\n if acedssget_t null null null ssname='RTNORM)' acutprintf_t\n return acdbobjectid ads_name ename acedssnamessname 0 ename acdbgetobjectidcutlineid ename cutpolylines cutpolylinescutlines cutlineid extern c acrx::appretcode acrxentrypointacrx::appmsgcode msg void pkt switch msg case acrx::kinitappmsg: acrxdynamiclinker->unlockApplication(pkt);
        acrxRegisterAppMDIAware(pkt);
        acutPrintf(_T("\n加载一键剪切多段线功能"));
        break;
    case AcRx::kUnloadAppMsg:
        acutPrintf(_T("\n卸载一键剪切多段线功能"));
        break;
    default:
        break;
    }
    return AcRx::kRetOK;
}

在这个示例中,我们首先提示用户选择被剪切的多段线对象,然后使用 acedSSGet() 函数获取选择集。接着,我们遍历选择集,将每个对象转换为 AcDbObjectId 并添加到 cutLines 数组中。然后,我们提示用户选择修剪对象,并获取其 AcDbObjectId。最后,我们调用 CutPolylines 函数进行剪切操作。

请注意,这个示例代码假设用户每次只选择一个修剪对象。如果需要支持多个修剪对象,你需要相应地修改代码。此外,剪切操作的具体实现需要根据实际需求来完成,这里没有提供具体的剪切算法。


提问:将处理闭合多段线的剪切这里面的实现代码写出来

MarsCode AI:

好的,以下是处理闭合多段线剪切的示例实现代码。这里使用了
AcDbPolyline::getOffsetCurves() 方法来获取多段线的偏移曲线,然后根据这些曲线来剪切其他多段线。

cpp

// 处理闭合多段线的剪切
for (int i = 0; i < cutlines.length i acdbentity lineent='nullptr;' acdbopenobjectlineent cutlinesi acdb::kforread if lineent->isKindOf(AcDbPolyline::desc()))
    {
        AcDbPolyline* line = AcDbPolyline::cast(lineEnt);
        if (line->isClosed())
        {
            // 闭合多段线之间的剪切,将其切分成几个独立的闭合多段线
            AcDbVoidPtrArray offsetCurves;
            cutLine->getOffsetCurves(1.0, AcDb::OffsetCurve::kBoth, offsetCurves);
            for (int j = 0; j < offsetcurves.length j acdbcurve offsetcurve='AcDbCurve::cast(offsetCurves[j]);' if offsetcurve ... else ... lineent->close();
        delete lineEnt;
    }
}

请注意,上述代码中的 //... 部分需要根据实际需求来实现具体的剪切算法。例如,你可以使用
AcDbCurve::getClosestPointTo() 方法来找到多段线上与偏移曲线最近的点,然后根据这些点来分割多段线。

此外,由于
AcDbPolyline::getOffsetCurves() 方法返回的是 AcDbVoidPtrArray,你需要将其转换为 AcDbCurve* 数组来使用。在使用完这些曲线后,记得释放它们所占用的内存。

最后,记得在实现剪切算法时考虑到所有可能的情况,例如多段线的自相交、与修剪对象的重叠等。

原文链接:,转发请注明来源!