WEB端在线CAD中实现测量圆、测量面积的方法

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
函数计算FC,每月15万CU 3个月
简介: 实现在线CAD中测量圆和测量面积的功能开发,用户点击目标圆对象将自动标记出这个圆的半径、面积值和周长值,同时可以自定义选择标注文字的位置,测量圆功能能够快速掌握目标圆对象的数据信息,方便统计工程量。

一、前言

本章将介绍如何利用mxcad插件实现在CAD图纸中测量圆和测量面积的功能,用户点击目标圆对象将自动标记出这个圆的半径、面积值和周长值,同时可以自定义选择标注文字的位置,测量圆功能能够快速掌握目标圆对象的数据信息,方便统计工程量。
测量面积功能(多边形、矩形)以多边形的每一个顶点来确定多边形的形状和位置,通过点击矩形的量角点来确定矩形的大小和位置,也可以自定义标注文字的位置。

二、测量圆的功能实现​

2.1.实现自定义圆标注类
为了方便后期管理与修改标注,可以通过继承McDbCustomEntity自定义实体类来扩展实现圆标注类。其中在mxcad中圆对象对应的实体类为McDbCircle,该类提供了获取或设置圆相关信息的属性或方法,我们可以根据功能需求去选择调用。

在测量圆功能中需要获取圆对象的半径、面积与周长,因此可以调用McDbCircle.radius属性获取圆半径,McDbCircle.getArea()方法或直接计算来获取圆面积,以及McDbCircle.getLength()方法获取圆周长。然后利用McDbMText构造测量信息多文本对象,将圆的标注信息绘制在页面中,参考代码如下:

// 自定义圆标注类
class McDbTestMeasuringCircle extends McDbCustomEntity {
   
    // 定义McDbTestMeasuringCircle内部的点对象 
    // 圆心
    private center: McGePoint3d = new McGePoint3d();
    // 标注点
    private position: McGePoint3d = new McGePoint3d();
    // 圆半径
    private radius: number;
    // 构造函数
    constructor(imp?: any) {
   
        super(imp);
    }
    // 创建函数
    public create(imp: any) {
   
        return new McDbTestMeasuringCircle(imp)
    }
    // 获取类名
    public getTypeName(): string {
   
        return "McDbTestMeasuringCircle";
    }
    //设置或获取圆半径
    public set circleRadius(val: number) {
   
        this.radius = val;
    }
    public get circleRadius(): number {
   
        return this.radius;
    }
    // 读取自定义实体数据center、position、radius
    public dwgInFields(filter: IMcDbDwgFiler): boolean {
   
        this.center = filter.readPoint("center").val;
        this.position = filter.readPoint("position").val;
        this.radius = filter.readDouble("radius").val;
        return true;
    }
    // 写入自定义实体数据center、position、radius
    public dwgOutFields(filter: IMcDbDwgFiler): boolean {
   
        filter.writePoint("center", this.center);
        filter.writePoint("position", this.position);
        filter.writeDouble("radius", this.radius);
        return true;
    }
    // 移动自定义对象的夹点
    public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
   
        this.assertWrite();
        this.position.x += dXOffset;
        this.position.y += dYOffset;
        this.position.z += dZOffset;
    };
    // 获取自定义对象的夹点
    public getGripPoints(): McGePoint3dArray {
   
        let ret = new McGePoint3dArray()
        ret.append(this.position);
        return ret;
    };
    // 绘制实体
    public worldDraw(draw: MxCADWorldDraw): void {
   
        // 绘制标注圆与标注信息
        const circle = new McDbCircle();
        circle.center = this.center;
        circle.radius = this.radius;
        const length = circle.getLength().val;
        const radius = circle.radius;
        const area = Math.PI * radius * radius;
        const mText = new McDbMText();
        mText.contents = `半径:${
     radius.toFixed(2)} \\P 周长:${
     length.toFixed(2)} \\P 面积:${
     area.toFixed(2)}`
        mText.textHeight = radius / 6;
        mText.attachment = McDb.AttachmentPoint.kMiddleCenter;
        mText.location = this.position;
        mText.trueColor = circle.trueColor = this.trueColor;
        draw.drawEntity(mText);
        draw.drawEntity(circle);
    }
    // 设置pt1
    public setCenter(pt: McGePoint3d) {
   
        this.assertWrite();
        this.center = pt.clone();
    }
    // 获取pt1
    public getCenter() {
   
        return this.center;
    }
    // 获取position
    public setPosition(pt: McGePoint3d) {
   
        this.assertWrite();
        this.position = pt.clone();
    }
    // 获取position
    public getPosition() {
   
        return this.position;
    }
}

2.2 注册自定义类信息
运行代码:

new McDbTestMeasuringCircle().rxInit();

2.3 编写方法调用McDbTestMeasuringCircle自定义圆标注类实现测量圆功能

2.3.1 获取目标圆对象,得到相关数据信息

利用选择实体对象MxCADUiPrEntity()根据用户鼠标点击的坐标得到对应的实体,其中需要只选择圆对象,因此,我们再调用MxCADResbuf()为选择实体对象设置过滤器来过滤出目标实体,参考代码如下:

// 选择实体对象
const getEnt = new MxCADUiPrEntity();
// 设置提示信息
getEnt.setMessage("请选择一个圆对象");
// 设置过滤器
const filter = new MxCADResbuf([DxfCode.kEntityType, "CIRCLE"]);
getEnt.setFilter(filter);
// entId过滤选择后的圆实体对象ID
const entId = await getEnt.go();
if (!entId.id) return;
// 获取圆相关信息
const circle = entId.getMcDbEntity() as McDbCircle;
const mCircle = new McDbTestMeasuringCircle();
mCircle.setCenter(circle.center);
mCircle.circleRadius = circle.radius;

2.3.2 指定标注点并绘制圆标注对象

利用MxCADUiPrPoint取点对象在页面中交互取点。在取点过程中通过MxCADUiPrPoint.setUserDraw()方法动态绘制标注对象,使用户更加直观的观察到标注对象的位置变化,参考代码如下:

// 设置取点对象
const getPt = new MxCADUiPrPoint();
// 设置提示信息
getPt.setMessage('请指定文字位置');
// 动态绘制
getPt.setUserDraw((pt, pw) => {
   
    pw.setColor(0xFF0000);
    mCircle.setPosition(pt);
    pw.drawMcDbEntity(mCircle);
});
const point = await getPt.go();
if (!point) return;
// 设置标注文本位置
mCircle.setPosition(point);
// 设置圆标注对象颜色
mCircle.trueColor = new McCmColor(255, 0, 0)
const mxcad = MxCpp.getCurrentMxCAD();
// 绘制圆标注对象
mxcad.drawEntity(mCircle);

效果如下图:
1.测量圆1.png

三、测量面积的功能实现

3.1 实现自定义面积标注类
为了方便后期管理与修改标注,可以通过继承McDbCustomEntity自定义实体类来扩展实现面积标注类,在mxcad中多边形与矩形都是通过多段线绘制出来的,多段线对象对应的实体类为McDbPolyline,该类提供了获取或设置图形对象相关信息的属性或方法,根据功能需求去选择调用。

在测量面积(多边形、矩形)功能中,调用McDbPolyline.getLength()方法获取多段线对象的长度、以及在多段线闭合的情况下调用McDbPolyline.getArea()方法获取面积。然后利用McDbMText构造测量信息多文本对象,将对象的标注信息绘制在页面中,参考代码如下:

// 自定义面积标注类
class McDbTestAreaComment extends McDbCustomEntity {
   
    /** 点数组 */
    private ptArr: McGePoint3d[] = [];
    /** 标注点 */
    private pt: McGePoint3d;
    /** 字高 */
    private height: number = 50;
    /** 凸度数组 */
    private dbulges: number[] = [];
    /** 测量对象是否为矩形 */
    private isReactFlag: boolean = false;
    constructor(imp?: any) {
   
        super(imp);
    }
    public create(imp: any) {
   
        return new McDbTestAreaComment(imp)
    }
    /** 获取类名 */
    public getTypeName(): string {
   
        return "McDbTestAreaComment";
    }
    //设置或获取文本字高
    public set textHeight(val: number) {
   
        this.height = val;
    }
    public get textHeight(): number {
   
        return this.height;
    }
    //设置或获取测量对象是否为矩形
    public set isReact(val: boolean) {
   
        this.isReactFlag = val;
    }
    public get isReact(): boolean {
   
        return this.isReactFlag;
    }
    /** 读取数据 */
    public dwgInFields(filter: IMcDbDwgFiler): boolean {
   
        this.ptArr = filter.readPoints('ptArr').val;
        this.pt = filter.readPoint('pt').val;
        const _dbulges = filter.readString("dbulges").val;
        this.dbulges = _dbulges.split(',').map(Number);
        this.isReactFlag = filter.readLong("isReactFlag").val ? true : false;
        return true;
    }
    /** 写入数据 */
    public dwgOutFields(filter: IMcDbDwgFiler): boolean {
   
        filter.writePoints("ptArr", this.ptArr);
        filter.writePoint("pt", this.pt);
        const _dbulges = this.dbulges.toString();
        filter.writeString("dbulges", _dbulges);
        filter.writeLong("isReactFlag", this.isReactFlag ? 1 : 0);
        return true;
    }
    /** 移动夹点 */
    public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
   
        this.assertWrite();
        this.ptArr.forEach((point, index) => {
   
            if (index === iIndex) {
   
                point.x += dXOffset;
                point.y += dYOffset;
                point.z += dZOffset;
            }
        });
        if (iIndex === this.ptArr.length) {
   
            this.pt.x += dXOffset;
            this.pt.y += dYOffset;
            this.pt.z += dZOffset;
        }
    };
    /** 获取夹点 */
    public getGripPoints(): McGePoint3dArray {
   
        let ret = new McGePoint3dArray();
        this.ptArr.forEach(point => {
   
            ret.append(point);
        })
        ret.append(this.pt);
        return ret;
    };
    /** 动态绘制 */
    public worldDraw(draw: MxCADWorldDraw): void {
   
        const pl = new McDbPolyline();
        pl.isClosed = true;
        if (this.isReactFlag) {
   
            // 测量的是矩形,得到的就是矩形的两个角点
            pl.addVertexAt(this.ptArr[0], 0, 0.1, 0.1);
            pl.addVertexAt(new McGePoint3d(this.ptArr[1].x, this.ptArr[0].y), 0, 0.1, 0.1);
            pl.addVertexAt(this.ptArr[1], 0, 0.1, 0.1);
            pl.addVertexAt(new McGePoint3d(this.ptArr[0].x, this.ptArr[1].y), 0, 0.1, 0.1);
        } else {
   
            // 测量的是多边形
            this.ptArr.forEach((pt, index) => {
   
                pl.addVertexAt(pt, this.dbulges[index], 0.1, 0.1);
            });
        }
        // 获取对象数据信息
        const area = pl.getArea().val;
        const length = pl.getLength().val;
        // 构造对文本对象
        const text = new McDbMText();
        text.contents = `面积:${
     area.toFixed(2)}\\P周长:${
     length.toFixed(2)} `;
        text.attachment = McDb.AttachmentPoint.kMiddleCenter;
        text.location = this.pt;
        text.textHeight = MxFun.screenCoordLong2Doc(this.height);
        // 设置标注颜色
        text.trueColor = this.trueColor;
        draw.trueColor = this.trueColor;
        // 绘制标注对象
        draw.drawEntity(text);
        draw.drawEntity(pl);
    }
    /** 设置标注点 */
    public setPoint(pt: McGePoint3d) {
   
        this.assertWrite();
        this.pt = pt.clone();
    }
    /** 增加顶点 */
    public addVertex(pt: McGePoint3d, dbulge?: number) {
   
        this.assertWrite();
        this.ptArr.push(pt.clone());
        this.dbulges.push(dbulge ? dbulge : 0);
    }
    /** 获取标注点 */
    public getPoint() {
   
        return this.pt;
    }
}

3.2 注册自定义类信息
运行代码如下:

new McDbTestAreaComment().rxInit();

3.3 编写方法,调用McDbTestAreaComment自定义面积标注类实现测量面积(多边形、矩形)功能

3.3.1 测量多边形面积
测量多边形面积需要连续取点,且取点不少于3个。利用MxCADUiPrPoint取点对象在图纸中循环取点来确定需要测量多边形的位置与大小,并通过MxCADUiPrPoint.setKeyWords()为其设置关键字列表,使用户能够实现自主撤销操作或提前结束操作,方便交互,参考代码如下:

// 测量多边形面积
async function Mx_Area() {
   
    // 多边形顶点数值
    const ptArr: McGePoint3d[] = [];
    // 获取多边形第一个顶点
    const getPt1 = new MxCADUiPrPoint();
    getPt1.setMessage('请选择面积的第一个点');
    const pt1 = await getPt1.go();
    if (!pt1) return;
    ptArr.push(pt1);
    // 循环取点
    while (true) {
   
        const getPt = new MxCADUiPrPoint();
        getPt.setMessage('请选择下一个点');
        getPt.setKeyWords("[回退(B)/结束(O)]");
        getPt.setUserDraw((pt, pw) => {
   
            const draw_pl = new McDbPolyline();
            ptArr.forEach(point => {
   
                draw_pl.addVertexAt(point, 0, 0.1, 0.1);
            });
            draw_pl.addVertexAt(pt);
            pw.drawMcDbEntity(draw_pl);
        });
        const pt = await getPt.go();
        const key = getPt.keyWordPicked();
        if (key === 'B') {
   
            // 回退到上一个取点对象
            if (ptArr.length > 1) {
   
                ptArr.pop();
            }
        } else if (key === 'O') {
   
            // 结束取点
            break;
        } else {
   
            if (!pt) break;
            ptArr.push(pt);
        }
    };
    // 测量多边形至少取3个点
    if(ptArr.length < 2) return;
    // 构造面积标注对象并设置标注位置
    const mxcad = MxCpp.getCurrentMxCAD();
    const area = new McDbTestAreaComment();
    ptArr.forEach((point) => {
   
        area.addVertex(point, 0);
    });
    const position = new MxCADUiPrPoint();
    position.setMessage('请选择面积标注的位置');
    position.setUserDraw((pt, pw) => {
   
        pw.setColor(0xFF0000)  
        area.setPoint(pt);
        pw.drawMcDbEntity(area);
    })
    const positionPt = await position.go();
    if (!positionPt) return;
    area.setPoint(positionPt);
    area.trueColor = new McCmColor(255,0,0)
    mxcad.drawEntity(area);
}

3.3.2 测量矩形面积
测量矩形面积只需要选取矩形的两个角点就可以确定矩形的大小与位置,参考代码如下:

// 矩形面积
async function Mx_ReactArea() {
   
    // 设置测量矩形的两个角点
    const getPt1 = new MxCADUiPrPoint();
    getPt1.setMessage('请选择矩形的角点1');
    const pt1 = await getPt1.go();
    if (!pt1) return;
    const getPt2 = new MxCADUiPrPoint();
    getPt2.setMessage('请选择矩形的角点2');
    // 动态绘制矩形
    getPt2.setUserDraw((pt, pw) => {
   
        const pl = new McDbPolyline();
        pl.isClosed = true;
        pl.addVertexAt(pt1);
        pl.addVertexAt(new McGePoint3d(pt.x, pt1.y));
        pl.addVertexAt(pt);
        pl.addVertexAt(new McGePoint3d(pt1.x, pt.y));
        pw.drawMcDbEntity(pl);
    })
    const pt2 = await getPt2.go();
    if (!pt2) return;
    // 构造面积标注
    const reactArea = new McDbTestAreaComment();
    reactArea.isReact = true;
    reactArea.addVertex(pt1);
    reactArea.addVertex(pt2);
    // 设置标注位置
    const getPos = new MxCADUiPrPoint();
    getPos.setMessage('请设置面积标注的位置');
    getPos.setUserDraw((pt, pw) => {
   
        pw.setColor(0xFF0000)
        reactArea.setPoint(pt);
        pw.drawMcDbEntity(reactArea);
    });
    const position = await getPos.go();
    if (!position) return;
    reactArea.setPoint(position);
    // 设置标注颜色
    reactArea.trueColor = new McCmColor(255, 0, 0)
    MxCpp.getCurrentMxCAD().drawEntity(reactArea);
}

效果如下图:
测多边形面积1.png

相关文章
|
4天前
|
前端开发 API
(WEB前端编辑DWG)在线CAD如何实现图形识别功能
mxcad 提供的图形识别功能可帮助用户快速识别和提取 CAD 图纸中的各种图形,如直线、多段线、弧线、圆及图块,显著提升设计效率。此功能不仅适用于图形分类,还能进行数量统计和快速定位,减少手动操作。用户可通过 API 进行二次开发,自定义识别逻辑。具体步骤包括打开在线示例、选择识别功能、设置识别参数并开始识别。更多开发文档请关注公众号:梦想云图网页 CAD。
|
1月前
|
前端开发 JavaScript 持续交付
Web应用开发的方法
Web应用开发的方法
16 1
|
2月前
|
JavaScript 前端开发 开发者
JS 继承之谜:究竟有哪些神秘方法?Web 前端开发者必知的关键技巧待你揭开谜底!
【8月更文挑战第23天】JavaScript (JS) 是 Web 前端开发的关键语言,其中继承是面向对象编程的重要概念。本文探讨了 JS 中几种继承机制:原型链继承、构造函数继承及组合继承。原型链继承利用原型对象实现属性和方法的共享;构造函数继承通过在子类构造器内调用父类构造器实现私有属性的复制;组合继承结合两者优点,既支持属性共享又避免了属性被意外覆盖的风险。理解这些模式有助于开发者更高效地组织代码结构,提升程序质量。
29 1
|
2月前
|
Java 开发者 关系型数据库
JSF与AWS的神秘之旅:如何在云端部署JSF应用,让你的Web应用如虎添翼?
【8月更文挑战第31天】在云计算蓬勃发展的今天,AWS已成为企业级应用的首选平台。本文探讨了在AWS上部署JSF(JavaServer Faces)应用的方法,这是一种广泛使用的Java Web框架。通过了解并利用AWS的基础设施与服务,如EC2、RDS 和 S3,开发者能够高效地部署和管理JSF应用。文章还提供了具体的部署步骤示例,并讨论了使用AWS可能遇到的挑战及应对策略,帮助开发者更好地利用AWS的强大功能,提升Web应用开发效率。
51 0
|
2月前
|
存储 前端开发 开发者
Web 前端热点来袭!数组去重难题何解?快来探索这些超实用方法,引发开发者共鸣!
【8月更文挑战第23天】在Web前端开发中,去除数组中的重复项是提升数据准确性和效率的关键步骤。本文介绍了四种常用的数组去重方法:一是运用ES6的Set数据结构,通过构造Set对象并转换回数组,快速剔除重复值;二是结合for循环与`indexOf`方法,逐个检查元素是否已存在于新数组中;三是采用`forEach`循环与`includes`方法实现类似功能;四是利用`reduce`方法,以函数式编程方式完成累积检查和去重。这四种方法各有优势,可根据项目需求和环境选择使用。
48 0
|
2月前
|
开发框架 中间件 .NET
分享 ASP.NET Core Web Api 中间件获取 Request Body 两个方法
分享 ASP.NET Core Web Api 中间件获取 Request Body 两个方法
|
2月前
|
开发框架 .NET API
如何在 ASP.NET Core Web API 方法执行前后 “偷偷“ 作一些 “坏“ 事?初识 ActionFilterAttribute
如何在 ASP.NET Core Web API 方法执行前后 “偷偷“ 作一些 “坏“ 事?初识 ActionFilterAttribute
|
2月前
|
设计模式 开发框架 前端开发
使用 FastEndpoints 来垂直切割Web API的控制器方法
使用 FastEndpoints 来垂直切割Web API的控制器方法
‘;‘ expected,Missing semicolon.Syntax Missing semicolon multi (web,若依定义方法,修改method,之后在mounted()用this
‘;‘ expected,Missing semicolon.Syntax Missing semicolon multi (web,若依定义方法,修改method,之后在mounted()用this
|
3月前
|
Web App开发
软件开发常见流程之移动端调试方法,利用Chrome(谷歌浏览器)的模拟手机调试,搭建本地Web服务器,手机和服务器在一个局域网,通过手机访问服务器,使用服务器,利用ip实现域名访问
软件开发常见流程之移动端调试方法,利用Chrome(谷歌浏览器)的模拟手机调试,搭建本地Web服务器,手机和服务器在一个局域网,通过手机访问服务器,使用服务器,利用ip实现域名访问
下一篇
无影云桌面