(WEB CAD online )在线CAD实现圆孔标记功能

本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: 本文介绍了通过自定义实体 `McDbTestRoundHoleMark` 实现圆孔标记功能的方法。该功能支持多象限标记、可调节标记角度、多重标记及动态编辑,并自动计算包围盒以优化空间定位与选择操作。核心实现包括类结构定义、数据序列化、标记数据设置、夹点编辑及实体绘制等步骤。用户可通过插件初始化注册并创建圆孔标记,适用于工程图纸标注场景。在线Demo展示了实际效果,便于开发者参考与使用。

一、概述

圆孔标记是一种常用的工程图纸标注方式,用于标识圆形孔的位置和特征。本文档将详细介绍如何通过自定义实体(McDbTestRoundHoleMark)来实现圆孔标记功能。具体功能源码可下载MxDraw云图开发包后查看。

二、自定义实体类定义

2.1 类结构

export class McDbTestRoundHoleMark extends McDbCustomEntity {
   
    // 圆孔圆心
    private center: McGePoint3d;
    // 圆孔半径
    private radius: number;
    // 标记圆上的点集合
    private circlePoints: McGePoint3d[];
    // 标记中心点集合
    private midPoints: McGePoint3d[];
    // 标记圆弧中心点
    private circleMidPts: McGePoint3d[];
    // 标记基点
    private originPt: McGePoint3d;
    // 包围盒点
    private minPt: McGePoint3d;
    private maxPt: McGePoint3d;
}

2.2 核心属性说明

  • center: 圆孔的圆心坐标
  • radius: 圆孔的半径
  • circlePoints: 标记圆弧的端点集合
  • midPoints: 标记射线上的中点集合
  • circleMidPts: 标记圆弧的中心点集合
  • originPt: 标记的基准点
  • minPt/maxPt: 包围盒的最小/最大点

三、核心功能实现

3.1 数据序列化
将上述定义的圆孔标记内的属性通过dwgInFields、dwgOutFields两方法分别设置,使得在圆孔标记自定义实体内部能够写入或读取相关的实体数据。

// 读取自定义实体数据
public dwgInFields(filter: IMcDbDwgFiler): boolean {
   
    this.center = filter.readPoint("center").val;
    this.originPt = filter.readPoint("originPt").val;
    this.circlePoints = filter.readPoints("circlePoints").val;
    this.circleMidPts = filter.readPoints("circleMidPts").val;
    this.midPoints = filter.readPoints("midPoints").val;
    this.radius = filter.readDouble("radius").val;
    this.minPt = filter.readPoint("minPt").val;
    this.maxPt = filter.readPoint("maxPt").val;
    return true;
}
// 写入自定义实体数据
public dwgOutFields(filter: IMcDbDwgFiler): boolean {
   
    filter.writePoint("center", this.center);
    filter.writePoint("originPt", this.originPt);
    filter.writePoints("circlePoints", this.circlePoints);
    filter.writePoints("circleMidPts", this.circleMidPts);
    filter.writePoints("midPoints", this.midPoints);
    filter.writeDouble("radius", this.radius);
    filter.writePoint("minPt", this.minPt);
    filter.writePoint("maxPt", this.maxPt);
    return true;
}

3.2 标记数据设置
根据标记在不同象限下的向量方向记录标记内部具体的圆弧曲线首尾两点以及圆弧中点,为后续动态绘制标记实体提供点位。

public setRoundData(center: McGePoint3d, radius: number, quadrant: number = 1, count: number = 1, angle: number = Math.PI / 2) {
   
    this.center = this.originPt = center.clone();
    this.radius = radius;
    // 根据象限确定向量方向
    let vec: McGeVector3d;
    switch (quadrant) {
   
        case 1: vec = McGeVector3d.kXAxis.clone(); break;
        case 2: vec = McGeVector3d.kYAxis.clone(); break;
        case 3: vec = McGeVector3d.kXAxis.clone().negate(); break;
        case 4: vec = McGeVector3d.kYAxis.clone().negate(); break;
        default: vec = McGeVector3d.kXAxis.clone(); break;
    }
    // 计算标记点位
    const arcPt1 = this.center.clone().addvec(vec.clone().mult(this.radius));
    const arcPt2 = this.center.clone().addvec(vec.clone().rotateBy(angle / 2).mult(this.radius));
    const arcPt3 = this.center.clone().addvec(vec.clone().rotateBy(angle).mult(this.radius));
    // 设置标记点集合
    this.circlePoints = [arcPt1, arcPt3];
    this.circleMidPts = [arcPt2];
    // 计算射线中点
    const lMidPt = this.center.clone().addvec(arcPt1.sub(this.center).mult(0.5));
    const rMidPt = this.center.clone().addvec(arcPt3.sub(this.center).mult(0.5));
    this.midPoints = [lMidPt, rMidPt];
}

3.3 标记夹点设置
在 getGripPoints() 方法内放入作为实体夹点的点位,在moveGripPointsAt()方法内设置每个夹点被移动编辑后需要执行的操作,如移动标注基点后,标注实体内部的所有夹点都跟着移动;移动标注实体圆弧中心点后重新计算新点位下圆弧的大小;移动标记实体半径上的点后会修改标注基点和相关联圆弧的大小等。

// 移动自定义对象的夹点
    public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
   
        this.assertWrite();
        // 移动所有点
        const moveAllPoints = () => {
   
            // 基点移动,所有点都跟着移动
            this.originPt.x += dXOffset;
            this.originPt.y += dYOffset;
            this.originPt.z += dZOffset;

            this.center.x += dXOffset;
            this.center.y += dYOffset;
            this.center.z += dZOffset;

            const pointArr = [...this.circleMidPts, ...this.circlePoints, ...this.midPoints]
            pointArr.forEach(pt => {
   
                pt.x += dXOffset;
                pt.y += dYOffset;
                pt.z += dZOffset;
            });
        }

        // 重新计算所有半径上的中点
        const resetRMidPts = () => {
   
            this.circlePoints.forEach((pt, i) => {
   
                const rMidPt = this.center.clone().addvec(pt.sub(this.center).mult(0.5));
                this.midPoints[i] = rMidPt
            })
        }
        // 重新计算圆弧上的中心点
        const resetArcMidPts = () => {
   
            let num = 0;
            for (let i = 0; i < this.circlePoints.length; i += 2) {
   
                const arc = new McDbArc();
                arc.computeArc(this.circlePoints[i].x, this.circlePoints[i].y, this.circleMidPts[num].x, this.circleMidPts[num].y, this.circlePoints[i + 1].x, this.circlePoints[i + 1].y);
                const midPt = arc.getPointAtDist(arc.getLength().val / 2).val;
                this.circleMidPts[num] = midPt.clone();
                num += 1;
            }
        }
        if (iIndex === 0) {
   
            moveAllPoints()
        } else if (iIndex === 1) {
   
            const pt = this.center.clone();
            if (pt.distanceTo(this.originPt) < 0.0001) {
   
                moveAllPoints()
            } else {
   
                this.center.x += dXOffset;
                this.center.y += dYOffset;
                this.center.z += dZOffset;

                resetRMidPts();
            }
        } else if (iIndex < this.circlePoints.length + 2) {
   
            // 圆弧两端点移动=》半径中点+圆弧中点跟着移动
            const i = iIndex - 2;
            const pt = this.circlePoints[i].clone();
            pt.x += dXOffset;
            pt.y += dYOffset;
            pt.z += dZOffset;
            this.circlePoints[i] = pt;

            // 重新计算圆弧中心点
            resetArcMidPts();

            // 计算半径上的中心点
            const rMidPt = this.center.clone().addvec(pt.sub(this.center).mult(0.5));
            this.midPoints[i] = rMidPt

        } else if (iIndex < this.circlePoints.length + 2 + this.circleMidPts.length) {
   
            // 圆弧中心点移动=>重新计算圆弧中心点
            const i = iIndex - 2 - this.circlePoints.length;
            const pt = this.circleMidPts[i].clone();
            pt.x += dXOffset;
            pt.y += dYOffset;
            pt.z += dZOffset;
            this.circleMidPts[i] = pt;

            // 重新计算圆弧中心点
            resetArcMidPts();

        } else {
   
            const i = iIndex - 2 - this.circlePoints.length - this.circleMidPts.length;
            this.center.x += dXOffset;
            this.center.y += dYOffset;
            this.center.z += dZOffset;

            this.midPoints[i].x += dXOffset;
            this.midPoints[i].y += dYOffset;
            this.midPoints[i].z += dZOffset;

            this.circlePoints[i].x += dXOffset;
            this.circlePoints[i].y += dYOffset;
            this.circlePoints[i].z += dZOffset;

            // 重新计算圆弧中心点
            resetArcMidPts();

            // 计算半径上的中心点
            resetRMidPts()
        }
    };
    // 获取自定义对象的夹点
    public getGripPoints(): McGePoint3dArray {
   
        let ret = new McGePoint3dArray();
        ret.append(this.originPt);
        ret.append(this.center);
        this.circlePoints.forEach(pt => {
   
            ret.append(pt);
        })
        this.circleMidPts.forEach(pt => {
   
            ret.append(pt);
        })
        this.midPoints.forEach(pt => {
   
            ret.append(pt);
        })
        return ret;
    };

3.4 实体绘制
通过上述步骤中的操作我们可以得到标注内部的圆弧点位,根据这些点位我们就能够计算出圆弧所在的位置并通过创建 McDbHatch 填充类来绘制最终的标注实体。

public worldDraw(draw: MxCADWorldDraw): void {
   
    const allEntityArr: McDbEntity[] = [];
    // 绘制标记圆弧和射线
    for (let i = 0; i < this.circlePoints.length; i += 2) {
   
        const num = (i + 2) / 2;
        const bulges = MxCADUtility.calcBulge(
            this.circlePoints[i],
            this.circleMidPts[num - 1],
            this.circlePoints[i + 1]
        ).val;

        // 创建填充实体
        const hatch = new McDbHatch();
        hatch.appendLoop(
            new McGePoint3dArray([this.center, this.circlePoints[i], this.circlePoints[i + 1]]),
            [0, bulges, 0]
        );
        draw.drawEntity(hatch);
        allEntityArr.push(hatch);
    }

    // 计算包围盒
    this.getBox(allEntityArr);
}
   // 计算标注实体包围盒大小
    private getBox(entityArr: McDbEntity[]) {
   
        const mxcad = MxCpp.getCurrentMxCAD();
        let _minPt, _maxPt = null;
        entityArr.forEach(entity => {
   
            const {
    minPt, maxPt, ret } = entity.getBoundingBox();
            if (!_minPt) _minPt = minPt.clone();
            if (!_maxPt) _maxPt = maxPt.clone();
            if (minPt.x < _minPt.x) _minPt.x = minPt.x;
            if (minPt.y < _minPt.y) _minPt.y = minPt.y;
            if (maxPt.x > _maxPt.x) _maxPt.x = maxPt.x;
            if (maxPt.y > _maxPt.y) _maxPt.y = maxPt.y;
        });
        if (_minPt && _maxPt) {
   
            this.maxPt = _maxPt;
            this.minPt = _minPt
        }
    }

四、 使用方法

4.1 初始化注册

// 在插件初始化时注册自定义实体
new McDbTestRoundHoleMark().rxInit();
MxFun.addCommand("Mx_RoundHoleMark", Mx_RoundHoleMark);

4.2 创建圆孔标记

async function Mx_RoundHoleMark() {
   
    // 选择圆形实体
    const filter = new MxCADResbuf([DxfCode.kEntityType, "CIRCLE"]);
    const ss = new MxCADSelectionSet();
    if (!await ss.userSelect(t("请选择需要标记的圆:"), filter)) return;
    if (ss.count() == 0) return;
    // 为每个选中的圆创建标记
    ss.forEach(entityId => {
   
        const circle = entityId.getMcDbEntity() as McDbCircle;
        const roundHoleMark = new McDbTestRoundHoleMark();
        // 设置标记数据
        roundHoleMark.setRoundData(circle.center, circle.radius, [1, 1, Math.PI / 2]);
        roundHoleMark.trueColor = new McCmColor(0, 255, 0);
        // 绘制标记
        mxcad.drawEntity(roundHoleMark);
}

五、最佳实践

圆孔标注实体具有以下特性:

  1. 支持多象限标记:可在四个象限中选择标记方向
  2. 可调节标记角度:通过angle参数控制标记的张开角度
  3. 支持多重标记:可同时创建多个对称的标记
  4. 动态编辑:支持通过夹点编辑修改标记形状和位置
  5. 自动计算包围盒:用于空间定位和选择操作

根据McDbTestRoundHoleMark圆孔标注自定实体,我们可以结合MxCAD项目实现一个完整的圆孔标注功能(在线demo查看:https://demo2.mxdraw3d.com:3000/mxcad/),效果如下:
image-20250414144106324.png
image-20250414144700714.png

相关文章
|
2月前
|
人工智能
WEB CAD 利用AI编程实现多行文本的二次开发
本文介绍了在MxCAD插件中实现自定义编辑器实体类的功能,重点展示如何通过MxCADMText类在CAD中渲染和管理富文本。文章详细说明了注册同心圆实体文本的步骤,包括实现自定义文本类、注册自定义文本以及交互式修改参数的方法。此外,还扩展实践了粗糙度实体文本的注册与应用,涵盖构造粗糙度自定义实体文本类、注册及初始化过程,并通过示例图展示了运行效果。这些功能可帮助用户将复杂图形以文本形式插入多行文本中,提升项目设计效率。
|
8月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
120 4
|
4月前
|
存储 JSON JavaScript
WEB CAD插件通过上下文对象MxPluginContext修改UI界面的方法
本文介绍了如何使用MxPluginContext动态控制MxCAD项目的UI界面。通过该上下文对象,开发者可以灵活设置UI配置,如控制操作栏显隐、编辑按钮、添加侧边栏等。具体方法包括调用`getUiConfig()`获取并修改`mxUiConfig.json`中的属性,实现界面的定制化。此外,还提供了控制命令行聚焦的功能,解决输入框焦点锁定问题。详细代码示例和效果对比图展示了具体实现步骤,帮助开发者更好地适配项目需求。
|
10月前
HDFS web Interfaces功能解读
HDFS web Interfaces功能解读
WEB端在线CAD中实现测量圆、测量面积的方法
实现在线CAD中测量圆和测量面积的功能开发,用户点击目标圆对象将自动标记出这个圆的半径、面积值和周长值,同时可以自定义选择标注文字的位置,测量圆功能能够快速掌握目标圆对象的数据信息,方便统计工程量。
WEB端在线CAD中实现测量圆、测量面积的方法
|
8月前
|
JavaScript API 开发工具
(H5-Web3D-ThreeJS)在网页三维CAD中绘制窗户模型
本文介绍了如何使用mxcad3d在网页中创建一个简单的三维窗户模型。通过官方教程搭建环境,编写绘制窗户模型的代码,并在点击按钮后展示模型效果。最终模型包括窗框和玻璃部分,具备丰富的三维建模功能和便捷的API支持。
|
9月前
|
前端开发 API
(WEB前端编辑DWG)在线CAD如何实现图形识别功能
mxcad 提供的图形识别功能可帮助用户快速识别和提取 CAD 图纸中的各种图形,如直线、多段线、弧线、圆及图块,显著提升设计效率。此功能不仅适用于图形分类,还能进行数量统计和快速定位,减少手动操作。用户可通过 API 进行二次开发,自定义识别逻辑。具体步骤包括打开在线示例、选择识别功能、设置识别参数并开始识别。更多开发文档请关注公众号:梦想云图网页 CAD。
|
8月前
|
移动开发 前端开发 JavaScript
前端开发实战:利用Web Speech API之speechSynthesis实现文字转语音功能
前端开发实战:利用Web Speech API之speechSynthesis实现文字转语音功能
988 0
|
8月前
|
云安全 SQL 安全
数字时代下的Web应用程序安全:漏洞扫描服务的功能与优势
在当今这个数字化时代,Web应用程序不仅是企业与用户之间互动的桥梁,更是企业展示服务、传递价值的核心平台。然而,随着技术的不断进步,Web应用程序的复杂性也在不断增加,这为恶意攻击者提供了可乘之机。安全漏洞的频发,如SQL注入、跨站脚本攻击(XSS)、跨站请求伪造(CSRF)等,严重威胁着企业的数据安全、服务稳定性乃至经济利益。在这样的背景下,漏洞扫描服务作为一道重要的安全防线,显得尤为重要。本文将深入探讨漏洞扫描服务在面对Web应用程序安全问题时,所具备的功能优势。
|
8月前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
70 0