WEB CAD 利用AI编程实现多行文本的二次开发

本文涉及的产品
应用实时监控服务-用户体验监控,每月100OCU免费额度
可观测监控 Prometheus 版,每月50GB免费额度
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 本文介绍了在MxCAD插件中实现自定义编辑器实体类的功能,重点展示如何通过MxCADMText类在CAD中渲染和管理富文本。文章详细说明了注册同心圆实体文本的步骤,包括实现自定义文本类、注册自定义文本以及交互式修改参数的方法。此外,还扩展实践了粗糙度实体文本的注册与应用,涵盖构造粗糙度自定义实体文本类、注册及初始化过程,并通过示例图展示了运行效果。这些功能可帮助用户将复杂图形以文本形式插入多行文本中,提升项目设计效率。

前言

在最新版本的 mxcad 插件中,我们提供了一个名为MxCADMText的自定义编辑器实体类,用于在CAD中渲染和管理富文本编辑器。基于该类,我们可以将富文本编辑器中的强大功能转移实现在我们的MxCAD项目中,目前我们的在线demo中已经更新了多行文本编辑器的相关功能。

在原本的富文本编辑器功能上,我们将文本与CAD功能相结合实现了多行文本的扩展,用户可以根据自己项目的需求将实体以文本内容的形式插入到我们的多行文本内,接下来我们将详细讲述如何在MxCAD项目的多行文本编辑功能中插入自定义文本实体,富文本编辑功能示例:
image-20250417100548914.png

注册同心圆实体文本

下面我们将以在多行文本编辑器中插入一个同心圆实体文本作为示例,介绍基础的扩展步骤。

1.实现自定义文本类
MxCADMText类中注册的所有自定义文本实体都需要继承MxCADBaseCustomText这个自定义文本基类,否则多行文本实体内部将无法识别你的自定义文本。

     /**
    * 同心圆自定义文本类
    * 用于在MxCAD多行文本中插入同心圆
    */
   class MxCADConcentricCircles extends MxCADBaseCustomText {
   
     // 自定义文本的类型唯一标识
     type = "MxCADConcentricCircles";
     /**
      * 计算同心圆的尺寸
      * @param entity MxCAD多行文本实体
      * @param textNode 文本节点
      * @returns 计算数据,包含宽度和高度
      */
     calculate(entity: MxCADMText, textNode: MarksStyleText): MxCADCustomTextCalculateData {
   
       // 获取外圆半径
       const outerRadius = this.getOuterRadius(entity, textNode);
       // 计算同心圆占用的空间大小
       const width = outerRadius * 2;
       const height = outerRadius * 2;
       return {
   
         width,
         height
       };
     }
     /**
      * 创建同心圆实体
      * @param entity MxCAD多行文本实体
      * @param textNode 文本节点
      * @param calculateData 计算数据
      * @param renderData 渲染数据
      * @returns 创建的实体数组
      */
     create(
       entity: MxCADMText,
       textNode: MarksStyleText,
       calculateData: MxCADCustomTextCalculateData,
       renderData: CreateData
     ): (McDbEntity | McDbCustomEntity)[] {
   
       // 获取外圆半径
       const outerRadius = this.getOuterRadius(entity, textNode);
       // 计算中圆半径
       const middleRadius = outerRadius * 0.7;
       // 计算内圆半径
       const innerRadius = outerRadius * 0.4;
       // 创建同心圆实体
       const circles: McDbEntity[] = [];
       // 计算圆心位置
       // renderData.position是左上角的位置
       const leftTopPosition = renderData.position.clone();
       // 将圆心位置从左上角偏移一个半径的距离,使同心圆左上角与renderData.position对齐
       // 圆心坐标 = 左上角坐标 + 圆半径
       const centerX = leftTopPosition.x + outerRadius;
       const centerY = leftTopPosition.y - outerRadius;
       // 创建最终圆心坐标
       const centerPosition = new McGePoint3d(centerX, centerY, leftTopPosition.z);
       // 创建外圆
       const outerCircle = new McDbCircle();
       outerCircle.radius = outerRadius;
       outerCircle.center = centerPosition;
       circles.push(outerCircle);
       // 创建中圆
       const middleCircle = new McDbCircle();
       middleCircle.radius = middleRadius;
       middleCircle.center = centerPosition;
       circles.push(middleCircle);
       // 创建内圆
       const innerCircle = new McDbCircle();
       innerCircle.radius = innerRadius;
       innerCircle.center = centerPosition;
       circles.push(innerCircle);
       return circles;
     }
     /**
      * 获取外圆半径
      * @param entity MxCAD多行文本实体
      * @param textNode 文本节点
      * @returns 外圆半径
      */
     private getOuterRadius(entity: MxCADMText, textNode: MarksStyleText): number {
   
       // 根据文本字体大小动态计算圆的半径
       const fontSize = textNode?.fontSize || 1;
       // 调整半径计算,使圆的大小合适
       return fontSize * entity.textBaseHeight / 2.5;
     }
     constructor() {
   
       super();
     }
   }
AI 代码解读

注意:

create()方法用于创建实际的图形实体。
calculate()方法用于计算自定义文本在多行文本中占用的空间。
type属性用于定义自定义文本的类型标识,该type将在MxCADMText类中作为唯一标识。

2.注册自定义文本
在MxCAD项目内的MxPluginContext上下文对象中我们已经暴露出了registerEditorCustomTextPlugin()注册方法,将上述已经写好的类放入该方法中就可以在自定义文本中插入同心圆实体了。

/**
    * 注册同心圆自定义文本插件
    */
   const insertConcentricCircles = MxPluginContext.registerEditorCustomTextPlugin(
     new MxCADConcentricCircles(), 
     {
   
       // 双击图形时的回调函数
       onDbClick: (node) => {
   
         console.log("双击了同心圆:", node);
       },
       // UI数据
       uiData: {
   
         // 图标
         icon: "yuan",
         // 文本
         text: "同心圆",
         // 提示文本
         tip: "插入同心圆",
         // 点击事件
         onClick: () => {
   
           // 插入同心圆
           insertConcentricCircles({
   
             // 这里可以传入自定义参数
           });
         }
       }
     }
   );
AI 代码解读

insertConcentricCircles(props: any, isUpdate?: boolean)方法中的 props 为外部传入的参数对象,可以用于设置实体的参数绘制,设置后通过 MxCADConcentricCircles 类内部 calculate()create()方法内的 textNode.props中获取;isUpdate 参数是用于已经插入了实体对象并处于文本编辑状态时,单击或双击实体进行修改操作后通知多行文本修改节点内容。

// 插入同心圆并传入自定义参数
     insertConcentricCircles({
   
       // 例如,可以传入不同的半径比例
       radiusRatio: {
   
         outer: 1,
         middle: 0.7,
         inner: 0.4
       }
     });
     /** 
       *更新
       onDbClick: (node) => {
       // ... 处理node数据,更新params
       insertConcentricCircles(params, true);
       }
       */
AI 代码解读
    // 在create方法中使用这些参数:
     create(entity, textNode, calculateData, renderData) {
   
       // 获取自定义参数
       const radiusRatio = renderData.props?.radiusRatio || {
   
         outer: 1,
         middle: 0.7,
         inner: 0.4
       };
       const outerRadius = this.getOuterRadius(entity, textNode);
       const middleRadius = outerRadius * radiusRatio.middle;
       const innerRadius = outerRadius * radiusRatio.inner;
       // 其他代码...
     }
AI 代码解读

onDbClick:双击文本时的回调函数,该回调函数内有一个node回调参数,该参数内部包含了文本节点的数据,即MxCADConcentricCircles 类内部的textNode。利用该函数可实现交互式自定义文本,例如在双击时显示一个对话框来修改参数。

MxPluginContext.registerEditorCustomTextPlugin(
       new MxCADConcentricCircles(), 
       {
   
         onDbClick: (node) => {
   
           // 显示一个对话框来修改参数
           showDialog(node, (newParams) => {
   
             // 更新自定义文本
             updateCustomText(node, newParams);
           });
         },
         // 其他配置...
       }
     );
AI 代码解读

uiData:设置插入实体在编辑器中的ui配置,其中icon值可以设置为iconfont字体图标。

3.在项目初始时执行注册事件

   function rxInitCircle() {
   
      /**
      ...params
      设置初始参数
      */
     insertConcentricCircles(params) 
   }
AI 代码解读
   // MxCAD创建成功,相当于mxcad init\_mxcad事件.
   MxFun.on("mxcadApplicationCreatedMxCADObject", (param) => {
   
       rxInitCircle()
   }
AI 代码解读

4.运行效果演示:
image-20250417112823583.png
image-20250417112902359.png

扩展实践(注册粗糙度实体文本)

1.构造粗糙度自定义实体文本注册类

// 绘制最初始的文本实体
   const getEntity = (entity: MxCADMText, textNode: MarksStyleText) => {
   
     const roughness = new McDbTestRoughness();
     roughness.setPos(new McGePoint3d(0, 0, 0));
     roughness.rouDimHeight = (textNode?.fontSize ? textNode.fontSize : 1) * entity.textBaseHeight;
     const form = textNode.props;
     roughness.rougMarkType = form.selectSymbolNum;
     roughness.textLeftStr = form.textLeftStr;
     roughness.rougCornerType = form.rougCornerType === "无" ? "" : form.rougCornerType;
     roughness.isRoungSameRequire = form.isRoungSameRequire;
     roughness.isShowMostSymbols = form.isShowMostSymbols;
     const dataArr = form.textUpStr.filter((item) => item != "");
     roughness.textUpStr = JSON.parse(JSON.stringify(dataArr)).reverse();
     roughness.textDownStr = form.textDownStr.filter((item) => item != "");
     roughness.isAddRougLongLine = form.isAddLongLine;
     return roughness
   }
   // 构建文本注册类
   class MxCADTestRoughnessText extends MxCADBaseCustomText {
   
     // type为后续多行文本插入的唯一标识
     type = "MxCADTestRoughnessText"
     calculate(entity: MxCADMText, textNode: MarksStyleText): MxCADCustomTextCalculateData {
   
       const roughness = getEntity(entity, textNode);
       const box = roughness.getBoundingBox();
       const width = box.maxPt.x - box.minPt.x
       const height = box.maxPt.y - box.minPt.y;
       return {
   
         width,
         height
       }
     }
     create(entity: MxCADMText, textNode: MarksStyleText, calculateData: MxCADCustomTextCalculateData, renderData: CreateData): (McDbEntity | McDbCustomEntity)[] {
   
       const roughness = getEntity(entity, textNode);
       const pos = roughness.getPos();
       //设置粗糙度在文本中的位置
       const {
    minPt, maxPt } = roughness.getBoundingBox();
       const basePt = new McGePoint3d(minPt.x, maxPt.y);
       const v = pos.sub(basePt)
       const pt = renderData.position.clone().addvec(v)
       roughness.setPos(pt);
       if (entity.getMTextImp().entityType == 'mtext' && !entity.getMTextImp().isEditState) {
   
         return [roughness]
       } else {
   
         const entityArr = roughness.getAllEntity();
         return [...entityArr]
       }
     }
     constructor() {
   
       super()
     }
   }
AI 代码解读

2.注册粗糙度文本
粗糙度弹框的具体实现可以具体参考在云图开发包中MxCAD项目内的extools目录下的实现源码。

// 注册粗糙度文本
   function rxInitRoughnessText() {
   
     // 使用插件上下文中的函数
     const insertCustomText = MxPluginContext.registerEditorCustomTextPlugin(
       new MxCADTestRoughnessText(),
       {
   
         // 双击文本时的回调函数
         onDbClick: (node) => {
   
           showRoughnessDialog(true, node as MarksStyleText)
         },
         uiData: {
   
           icon: 'icon-a-1',
           tip: '粗糙度',
           onClick: () => {
   
             // 插入自定义公式
             showRoughnessDialog(false)
           }
         }
       }
     )
     const showRoughnessDialog = (isUpdate: boolean = false, textNode?: MarksStyleText) => {
   
       if (isUpdate) {
   
         const roughness = new McDbTestRoughness();
         const form = textNode.props;
         roughness.rougMarkType = form.selectSymbolNum;
         roughness.textLeftStr = form.textLeftStr;
         roughness.rougCornerType = form.rougCornerType === "无" ? "" : form.rougCornerType;
         roughness.isRoungSameRequire = form.isRoungSameRequire;
         roughness.isShowMostSymbols = form.isShowMostSymbols;
         roughnessHandle.value = roughness;
            const dataArr = form.textUpStr.filter((item) => item != "");
         roughness.textUpStr = JSON.parse(JSON.stringify(dataArr)).reverse();
         roughness.textDownStr = form.textDownStr.filter((item) => item != "");
         roughness.isAddRougLongLine = form.isAddLongLine;
       }
       dialog.showDialog(true, {
    title: t("表面粗糙度") }).then(async ({
    data, isCanceled }) => {
   
         // 需要等待cancel或者confirm调用才会触发
         if (!isCanceled) {
   
           insertCustomText(data.roughnessData, isUpdate)
         }
       });
     }
   }
AI 代码解读

3.初始化粗糙度自定义文本

   // MxCAD创建成功,相当于mxcad init\_mxcad事件.
   MxFun.on("mxcadApplicationCreatedMxCADObject", (param) => {
   
       rxInitRoughnessText()
   }
AI 代码解读

4.实践效果演示
初始插入,如下图:
image-20250417115508073.png
双击修改,如下图:
image-20250417115919030.png
修改后最终以多行文本形式绘制在图纸中,如下图:
image-20250417120049618.png

目录
打赏
0
13
13
0
70
分享
相关文章
突破网页数据集获取难题:Web Unlocker API 助力 AI 训练与微调数据集全方位解决方案
本文介绍了Web Unlocker API、Web-Scraper和SERP API三大工具,助力解决AI训练与微调数据集获取难题。Web Unlocker API通过智能代理和CAPTCHA绕过技术,高效解锁高防护网站数据;Web-Scraper支持动态内容加载,精准抓取复杂网页信息;SERP API专注搜索引擎结果页数据抓取,适用于SEO分析与市场研究。这些工具大幅降低数据获取成本,提供合规保障,特别适合中小企业使用。粉丝专属体验入口提供2刀额度,助您轻松上手!
46 2
给Web开发者的HarmonyOS指南01-文本样式
本系列教程适合 HarmonyOS 初学者,为那些熟悉用 HTML 与 CSS 语法的 Web 前端开发者准备的。
94 5
给Web开发者的HarmonyOS指南01-文本样式
WhisperChain:开源 AI 实时语音转文字工具!自动消噪优化文本,效率翻倍
WhisperChain 是一款基于 Whisper.cpp 和 LangChain 的开源语音识别工具,能够实时将语音转换为文本,并自动清理和优化文本内容,适用于会议记录、写作辅助等多种场景。
986 2
WhisperChain:开源 AI 实时语音转文字工具!自动消噪优化文本,效率翻倍
浙大通义联手推出慢思考长文本生成框架OmniThink,让AI写作突破知识边界
随着大模型(LLMs)的发展,AI 写作取得了较大进展。然而,现有的方法大多依赖检索知识增强生成(RAG)和角色扮演等技术,其在信息的深度挖掘方面仍存在不足,较难突破已有知识边界,导致生成的内容缺乏深度和原创性。
281 46
文本、图像、点云任意模态输入,AI能够一键生成高质量CAD模型了
《CAD-MLLM: Unifying Multimodality-Conditioned CAD Generation With MLLM》提出了一种新型系统CAD-MLLM,能够根据文本、图像、点云或其组合生成高质量的CAD模型。该系统基于大型语言模型(LLM),通过多模态数据对齐和渐进式训练策略,实现了高效的CAD模型生成。作者创建了首个包含文本、图像、点云和命令序列的多模态数据集Omni-CAD,包含约450K个实例。实验表明,CAD-MLLM在多个任务上表现出色,特别是在点云条件生成任务中显著优于现有方法。未来工作将聚焦于提升计算效率、增加数据多样性及探索新模态。
324 18
阿里云通义千问发布多款AI大模型 多模态、长文本能力全面升级!
阿里云通义千问发布多款AI大模型 多模态、长文本能力全面升级!
WEB CAD插件通过上下文对象MxPluginContext修改UI界面的方法
本文介绍了如何使用MxPluginContext动态控制MxCAD项目的UI界面。通过该上下文对象,开发者可以灵活设置UI配置,如控制操作栏显隐、编辑按钮、添加侧边栏等。具体方法包括调用`getUiConfig()`获取并修改`mxUiConfig.json`中的属性,实现界面的定制化。此外,还提供了控制命令行聚焦的功能,解决输入框焦点锁定问题。详细代码示例和效果对比图展示了具体实现步骤,帮助开发者更好地适配项目需求。
三行代码实现实时语音转文本,支持自动断句和语音唤醒,用 RealtimeSTT 轻松创建高效语音 AI 助手
RealtimeSTT 是一款开源的实时语音转文本库,支持低延迟应用,具备语音活动检测、唤醒词激活等功能,适用于语音助手、实时字幕等场景。
814 18
三行代码实现实时语音转文本,支持自动断句和语音唤醒,用 RealtimeSTT 轻松创建高效语音 AI 助手
VideoWorld:字节开源自回归视频生成模型,支持输入视频指导AI生成视频!弥补文本生成视频的短板
VideoWorld 是由字节跳动、北京交通大学和中国科学技术大学联合推出的自回归视频生成模型,能够从未标注的视频数据中学习复杂知识,支持长期推理和规划任务。
536 8
VideoWorld:字节开源自回归视频生成模型,支持输入视频指导AI生成视频!弥补文本生成视频的短板
Emotion-LLaMA:用 AI 读懂、听懂、看懂情绪,精准捕捉文本、音频和视频中的复杂情绪
Emotion-LLaMA 是一款多模态情绪识别与推理模型,融合音频、视觉和文本输入,通过特定情绪编码器整合信息,广泛应用于人机交互、教育、心理健康等领域。
313 11
Emotion-LLaMA:用 AI 读懂、听懂、看懂情绪,精准捕捉文本、音频和视频中的复杂情绪

云原生

+关注
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等