(网页CAD插件)在线CAD二开形位公差标注

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
MSE Nacos 企业版免费试用,1600元额度,限量50份
函数计算FC,每月15万CU 3个月
简介: 本文介绍了基于mxcad插件实现形位公差标注功能的方法。形位公差用于控制零件的几何形状与位置误差,依据国家标准GB/T 1182-2018,分为形状、方向、位置和跳动四类。文章详细解析了形位公差的基本要素,如被测要素、基准要素、公差带与公差框格,并通过自定义实体类实现形位公差的绘制、数据存储与编辑功能。同时提供了使用方法与注意事项,确保功能稳定运行。

一、前言

形位公差是指对零件几何要素的形状误差和位置误差所允许的最大变动量,它与传统的尺寸公差不同,不仅关注长度或直径等线性尺寸的变化,还关注零件的几何特性是否符合设计意图。在本篇文章中我们将介绍如何通过mxcad插件根据形位公差的特性来实现形位公差标注功能。

二、形位公差的分类

形位公差的所有公差代号如下图所示:
image-20250616145741768.png

根据国家标准 GB/T 1182-2018(等同于 ISO 1101),形位公差主要分为以下几类:

  1. 形状公差(Form Tolerance)
  2. 方向公差(Orientation Tolerance)
  3. 位置公差(Location Tolerance)
  4. 跳动公差(Runout Tolerance)

三、形位公差的基本要素

  1. 被测要素:需要控制其形状或位置的几何要素。
  2. 基准要素:作为参照的标准几何要素,通常用大写字母 A、B、C 表示。
  3. 公差带:允许误差存在的区域范围,通常是二维或三维的空间区域。
  4. 公差框格:标注形位公差信息的图形符号,包含:公差类型符号、公差值、基准字母(如果有)。
    image-20250616150303532.png

四、mxcad实现形位公差类

根据上面的介绍,我们可以根据形位公差的“特征控制框”来构建我们的形位公差自定义实体,结构如下:

[公差符号]
[公差值]
[基准A]
[基准B]

4.1.类定义与继承

export class MxDbGeometricTolerances extends McDbCustomEntity {
   
    // 类实现
}
AI 代码解读

4.2.核心属性

// 标注起点
private startPoint: McGePoint3d = new McGePoint3d();
// 标注转折点
private turningPoint: McGePoint3d = new McGePoint3d();
// 标注点
private dimPoint: McGePoint3d = new McGePoint3d();
// 标注终点
private endPoint: McGePoint3d = new McGePoint3d();
// 标注大小
private size: number = 4;
// 是否显示全周符号
private isShowFull: boolean = false;
// 公差内容
private toleranceContents: toleranceContent[] = [];
// 附注上
private notesUp: string = '';
// 附注下
private notesDown: string = '';
AI 代码解读

4.3.公差代号枚举

export enum symbolName {
   
    Straightness = 'u',        // 直线度
    Flatness = 'c',           // 平面度
    Roundness = 'e',          // 圆度
    Cylindricity = 'g',       // 圆柱度
    LineContourdegree = 'k',  // 线轮廓度
    SurfaceContourDegree = 'd',// 面轮廓度
    Parallelism = 'f',        // 平行度
    Perpendicularity = 'b',   // 垂直度
    TiltDegree = 'a',         // 倾斜度
    PositionalDegree = 'j',   // 位置度
    Coaxiality = 'r',         // 同轴度
    SymmetryDegree = 'i',     // 对称度
    CircleJumping = 'h',      // 圆跳动
    FullBeat = 't',           // 全跳动
    None = ''                 // 无
}
AI 代码解读

五、主要功能实现

5.1.绘制功能

5.1.1 箭头和引线绘制

private drawArrow(): McDbEntity[] {
   
    // 绘制箭头
    const pt1 = this.startPoint;
    const pt2 = this.turningPoint;
    const arrowLength = this.size;
    const vec = pt2.sub(pt1).normalize().mult(arrowLength);
    const pt = pt1.clone().addvec(vec);
    const _vec = vec.clone().rotateBy(Math.PI / 2).normalize().mult(arrowLength / 8);
    const pt3 = pt.clone().addvec(_vec);
    const pt4 = pt.clone().subvec(_vec);
    const solid = new McDbHatch();
    solid.appendLoop(new McGePoint3dArray([pt1, pt3, pt4]));
    // 绘制引线
    const points = [this.startPoint, this.turningPoint, this.dimPoint, this.endPoint];
    const pl = new McDbPolyline();
    points.forEach(pt => pl.addVertexAt(pt));
    return [solid, pl];
}
AI 代码解读

5.1.2 公差代号绘制

    // 绘制公差代号
    private drawCode(topPt: McGePoint3d, endPt: McGePoint3d, boxHeight: number): McDbEntity[] {
   
        const entityArr: McDbEntity[] = [];
        // 首先绘制整体code边框
        const pl = new McDbPolyline();
        pl.isClosed = true;
        const v = McGeVector3d.kXAxis.clone().mult(boxHeight);
        const ptArr = [endPt, topPt, topPt.clone().addvec(v), endPt.clone().addvec(v)];
        ptArr.forEach(pt => pl.addVertexAt(pt));
        entityArr.push(pl);
        // 合并相邻公差代号
        const mergeAdjacent = (arr) => {
   
            const result = [];
            let i = 0;
            while (i < arr.length) {
   
                let j = i + 1;
                // 找到连续相同的元素
                while (j < arr.length && arr[j] === arr[i]) {
   
                    j++;
                }
                // 推入当前值和个数
                result.push({
   
                    value: arr[i],
                    count: j - i
                });
                // 移动指针到下一个不同的位置
                i = j;
            }
            return result;
        }
        const arr = this.toleranceContents.map(item => item.toleranceCode);
        const res = mergeAdjacent(arr);
        const vec_x = McGeVector3d.kXAxis.clone().mult(boxHeight);
        res.forEach(item => {
   
            // 绘制公差代号
            const text = new McDbMText();
            text.textHeight = this.size * (3 / 4);
            text.contents = item.value;
            text.attachment = McDb.AttachmentPoint.kBottomMid;
            const v = endPt.sub(topPt).normalize().mult(boxHeight * item.count);
            const center = topPt.clone().addvec(v.clone().mult(1 / 2)).addvec(vec_x.clone().mult(1 / 2));
            text.location = center;
            text.textStyle = 'cxgdt';
            topPt.addvec(v);
            entityArr.push(text);
            text.reCompute();
            const {
    maxPt, minPt } = MxCADUtility.getTextEntityBox(text, false);  
            if(minPt.distanceTo(maxPt) > text.textHeight*3){
   
                maxPt.addvec(McGeVector3d.kXAxis.clone().negate().mult(text.textHeight*(7/4)));
            }
            const midPt = minPt.clone().addvec(maxPt.sub(minPt).mult(1 / 2));
            text.move(midPt, center);
            const line = new McDbLine(topPt, topPt.clone().addvec(vec_x));
            entityArr.push(line)
        });
        return entityArr
    }
AI 代码解读

5.1.3 公差内容绘制

 // 绘制公差内容
    private drawToleranceContents(topPt: McGePoint3d, endPt: McGePoint3d, boxHeight: number): {
    MText: MxCADMText[], entityArr: McDbEntity[], max_x: number } {
   
        const entityArr: McDbEntity[] = [];
        const MText: MxCADMText[] = [];
        const mxcad = MxCpp.getCurrentMxCAD();
        /**
         * 公差1标注:3个标注中记录出X最大值
         */
        let max_x = topPt.x;
        const v_spacing = McGeVector3d.kXAxis.clone().mult(this.size / 4);
        const vec_y = McGeVector3d.kYAxis.clone().mult(boxHeight).negate();
        this.toleranceContents.forEach((item, ind) => {
   
            const _topPt = topPt.clone();
            const _endPt = endPt.clone();
            if (item.tolerance.length) {
   
                _topPt.addvec(v_spacing).addvec(vec_y.clone().mult(ind));
                const _v = McGeVector3d.kYAxis.clone().mult(boxHeight / 2 - this.size * (3 / 8)).negate();
                item.tolerance.forEach((str, index) => {
   
                    if (index === 4 || (index === 3 && (str === '{' || str === '@'))) {
   
                        const mText = new MxCADMText()
                        mText.data = [{
   
                            type: 'paragraph',
                            children: [
                                {
    text: str, font: 'cxgdtshp.shx' },
                            ]
                        }];
                        mText.position = _topPt.clone().addvec(_v);
                        mText.textBaseHeight = this.size * (3 / 4);
                        MText.push(mText);
                        const v = McGeVector3d.kXAxis.clone().mult(this.size);
                        const pt = mText.position.clone().addvec(v);
                        _topPt.x = _endPt.x = pt.x;
                    } else {
   
                        const text = new McDbMText();
                        text.contents = str;
                        text.location = _topPt.clone().addvec(_v);
                        text.textHeight = this.size * (3 / 4);
                        if (index == 2 || index == 4) {
   
                            text.textStyle = 'cxgdtshp';
                        } else if (index == 3 && str !== '{') {
   
                            text.textStyle = 'cxgdt'
                        } else {
   
                            text.textStyleId = mxcad.getDatabase().getCurrentlyTextStyleId()
                        }
                        text.reCompute();
                        const {
    maxPt, minPt } = MxCADUtility.getTextEntityBox(text, false);
                        _topPt.x = _endPt.x = maxPt.x;
                        entityArr.push(text);
                    }
                });
            };
            if (_topPt.x > max_x) max_x = _topPt.x;
        });
        if (max_x > topPt.x) {
   
            this.toleranceContents.forEach((item, index) => {
   
                const pl = new McDbPolyline();
                const topPt_max = new McGePoint3d(max_x, topPt.y);
                const endPt_max = new McGePoint3d(max_x, endPt.y);
                const points = [topPt, topPt_max.clone().addvec(v_spacing), endPt_max.clone().addvec(v_spacing)];
                points.forEach(pt => pl.addVertexAt(pt));
                entityArr.push(pl);
                topPt.addvec(vec_y);
                if (index === this.toleranceContents.length - 1) {
   
                    const line = new McDbLine(endPt_max.clone().addvec(v_spacing), endPt);
                    entityArr.push(line);
                }
            });
            max_x = new McGePoint3d(max_x, topPt.y).addvec(v_spacing).x;
        };
        return {
    entityArr, MText, max_x }
    }
AI 代码解读

5.1.4 绘制基准内容

// 绘制基准内容
    private drawBenchmark(topPt: McGePoint3d, endPt: McGePoint3d, boxHeight: number): {
    entityArr: McDbEntity[], MText } {
   
        const mxcad = MxCpp.getCurrentMxCAD();
        const _v = McGeVector3d.kYAxis.clone().mult(boxHeight / 2 - this.size * (3 / 8)).negate();
        const vec_y = McGeVector3d.kYAxis.clone().mult(boxHeight).negate();
        const v_spacing = McGeVector3d.kXAxis.clone().mult(this.size / 4);
        let max_x = topPt.x;
        const lineX = [];
        const MText: MxCADMText[] = []
        const getTextEnts = (contents: Array<string[]>, _topPt: McGePoint3d): McDbEntity[] => {
   
            const entity = [];
            let endPt = _topPt.clone();
            _topPt.addvec(v_spacing)
            if (contents.length === 2 && contents.filter(item => item.length != 0).length === 2) contents.splice(1, 0, ['-']);
            contents.forEach((arr, index) => {
   
                if (arr.length) {
   
                    arr.forEach((str, ind) => {
   
                        if (ind === 1 && str === '{') {
   
                            const mText = new MxCADMText()
                            mText.data = [{
   
                                type: 'paragraph',
                                children: [
                                    {
    text: str, font: 'cxgdtshp.shx' },
                                ]
                            }];
                            mText.position = _topPt.clone().addvec(_v);
                            mText.textBaseHeight = this.size * (3 / 4);
                            MText.push(mText);
                            const v = McGeVector3d.kXAxis.clone().mult(this.size);
                            const pt = mText.position.clone().addvec(v);
                            _topPt.x = endPt.x = pt.x;
                        } else {
   
                            const text = new McDbMText();
                            text.contents = str;
                            text.location = _topPt.clone().addvec(_v);
                            text.textHeight = this.size * (3 / 4);
                            if (ind == 1) {
   
                                text.textStyle = 'CXGDT';
                            } else {
   
                                text.textStyleId = mxcad.getDatabase().getCurrentlyTextStyleId()
                            }
                            text.reCompute();
                            const {
    maxPt, minPt } = MxCADUtility.getTextEntityBox(text, false);
                            if (max_x < maxPt.x) max_x = maxPt.x;
                            endPt.x = maxPt.x;
                            entity.push(text);
                            _topPt.x = maxPt.x;
                        }
                    })
                }
            });
            if (max_x < endPt.x) max_x = endPt.x;
            return entity;
        }
        const entityArr: McDbEntity[] = [];
        const maxXArr: number[] = [];
        //先统一绘制基准1、2、3
        const bNames = ['b1', 'b2', 'b3'];
        let textEnd_x = topPt.x;
        bNames.forEach((name, index) => {
   
            if (index != 0 && lineX.length) {
   
                textEnd_x = Math.max(...lineX)
                maxXArr.push(textEnd_x)
            };
            lineX.length = 0;
            this.toleranceContents.forEach((item, ind) => {
   
                if (item.Benchmark[name]?.length && item.Benchmark[name].filter(i => i.length).length > 0) {
   
                    const _topPt = new McGePoint3d(textEnd_x, topPt.clone().addvec(vec_y.clone().mult(ind)).y);
                    entityArr.push(...getTextEnts(item.Benchmark[name], _topPt));
                    const pt = new McGePoint3d(max_x, topPt.y);
                    pt.addvec(v_spacing);
                    max_x = pt.x;
                    lineX.push(max_x)
                }
            })
        })
        if (entityArr.length > 0) {
   
            maxXArr.forEach(x => {
   
                const line = new McDbLine(new McGePoint3d(x, topPt.y), new McGePoint3d(x, endPt.y));
                entityArr.push(line)
            })
            const line = new McDbLine(new McGePoint3d(max_x, topPt.y), new McGePoint3d(max_x, endPt.y));
            const _line = new McDbLine(endPt, new McGePoint3d(max_x, endPt.y));
            entityArr.push(line, _line);
            this.toleranceContents.forEach((item, index) => {
   
                if (index != 0) topPt.addvec(vec_y.clone());
                const line = new McDbLine(topPt, new McGePoint3d(max_x, topPt.y));
                entityArr.push(line)
            });
        }
        return {
    entityArr, MText }
    }
AI 代码解读

5.1.5 动态绘制

 // 绘制实体
    public worldDraw(draw: MxCADWorldDraw): void {
   
        const mxcad = MxCpp.getCurrentMxCAD();
        const textStyle = ['cxgdtshp', 'cxgdt'];
        textStyle.forEach(name => {
   
            if (!mxcad.getDatabase().getTextStyleTable().has(name)) {
   
                MxCpp.App.loadFonts([`${
     name}.shx`], [], [`${
     name}.shx`], () => {
   
                    mxcad.addTextStyle(name, `${
     name}.shx`, `${
     name}.shx`);
                });
            }
        })
        const {
    MText, allEntityArr } = this.getAllEnitty();
        MText.forEach((ent: MxCADMText) => {
   
            ent.worldDraw(draw);
        });
        allEntityArr.forEach((ent: McDbEntity) => {
   
            draw.drawEntity(ent);
        })
    }
    // 获取所有实体
    private getAllEnitty(): {
    allEntityArr: McDbEntity[], MText: MxCADMText[] } {
   
        const allEntityArr = [];
        // 绘制箭头
        const entity = this.drawArrow();
        allEntityArr.push(...entity);
        //  绘制全周符号
        const types = [symbolName.LineContourdegree, symbolName.SurfaceContourDegree];
        if (this.toleranceContents.length === 1 && types.includes(this.toleranceContents[0].toleranceCode) && this.isShowFull) {
   
            const circle = new McDbCircle(this.dimPoint.x, this.dimPoint.y, 0, this.size * (7 / 16));
            allEntityArr.push(circle);
        }
        // 绘制公差标注
        const boxHeight = this.size * (7 / 4);
        const vec = McGeVector3d.kYAxis.clone().mult(boxHeight * (this.toleranceContents.length / 2))
        const topPt = this.endPoint.clone().addvec(vec);
        const endPt = this.endPoint.clone().addvec(vec.clone().negate());
        // 绘制公差代号
        allEntityArr.push(...this.drawCode(topPt.clone(), endPt.clone(), boxHeight));
        // 绘制公差内容
        const vec_x = McGeVector3d.kXAxis.clone().mult(boxHeight);
        const {
    MText, entityArr, max_x } = this.drawToleranceContents(topPt.clone().addvec(vec_x), endPt.clone().addvec(vec_x), boxHeight);
        allEntityArr.push(...entityArr);
        // 绘制基准一二三
        const {
    MText: _MText, entityArr: _entityArr } = this.drawBenchmark(new McGePoint3d(max_x, topPt.y), new McGePoint3d(max_x, endPt.y), boxHeight)
        allEntityArr.push(..._entityArr);
        MText.push(..._MText);
        // 绘制上下附注
        const arr = [this.notesUp, this.notesDown];
        arr.forEach((item, index) => {
   
            const text = new McDbMText();
            text.contents = item;
            text.textHeight = this.size * (3 / 4)
            text.location = index == 0 ? topPt.clone().addvec(McGeVector3d.kYAxis.clone().mult(this.size)) : endPt.clone().addvec(McGeVector3d.kYAxis.clone().mult(this.size / 4).negate());
            allEntityArr.push(text);
        })
        return {
    allEntityArr, MText }
    }
AI 代码解读

5.2.数据存储

// 读取自定义实体数据
    public dwgInFields(filter: IMcDbDwgFiler): boolean {
   
        this.startPoint = filter.readPoint("startPoint").val;
        this.turningPoint = filter.readPoint("turningPoint").val;
        this.dimPoint = filter.readPoint("dimPoint").val;
        this.endPoint = filter.readPoint("endPoint").val;
        this.size = filter.readDouble("size").val;
        this.isShowFull = filter.readLong("isShowFull").val ? true : false;
        this.notesUp = filter.readString('notesUp').val;
        this.notesDown = filter.readString('notesDown').val;
        this.minPt = filter.readPoint("minPt").val;
        this.maxPt = filter.readPoint("maxPt").val;
        this.toleranceContents = JSON.parse(filter.readString('toleranceContents').val);
        return true;
    }
    // 写入自定义实体数据
    public dwgOutFields(filter: IMcDbDwgFiler): boolean {
   
        filter.writePoint("startPoint", this.startPoint);
        filter.writePoint("turningPoint", this.turningPoint);
        filter.writePoint("dimPoint", this.dimPoint);
        filter.writePoint("endPoint", this.endPoint);
        filter.writeDouble("size", this.size);
        filter.writeLong("isShowFull", this.isShowFull ? 1 : 0);
        filter.writeString("notesUp", this.notesUp);
        filter.writeString("notesDown", this.notesDown);
        filter.writePoint("minPt", this.minPt);
        filter.writePoint("maxPt", this.maxPt);
        filter.writeString('toleranceContents', JSON.stringify(this.toleranceContents));
        return true;
    }
AI 代码解读

5.3.夹点编辑功能

 // 移动自定义对象的夹点
    public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
   
        this.assertWrite();
        if (iIndex === 0) {
   
            this.startPoint.x += dXOffset;
            this.startPoint.y += dYOffset;
            this.startPoint.z += dZOffset;
        } else if (iIndex === 1) {
   
            this.turningPoint.x += dXOffset;
            this.turningPoint.y += dYOffset;
            this.turningPoint.z += dZOffset;
        } else if (iIndex === 2) {
   
            this.dimPoint.x += dXOffset;
            this.dimPoint.y += dYOffset;
            this.dimPoint.z += dZOffset;
            this.endPoint.x += dXOffset;
            this.endPoint.y += dYOffset;
            this.endPoint.z += dZOffset;
        } else if (iIndex === 3) {
   
            this.endPoint.x += dXOffset;
            this.endPoint.y += dYOffset;
            this.endPoint.z += dZOffset;
        }
    };
    // 获取自定义对象的夹点
    public getGripPoints(): McGePoint3dArray {
   
        let ret = new McGePoint3dArray()
        ret.append(this.startPoint);
        ret.append(this.turningPoint);
        ret.append(this.dimPoint);
        ret.append(this.endPoint);
        return ret;
    };
AI 代码解读

5.4.暴露内部属性方法

 //设置或获取标注大小
    public set dimSize(val: number) {
   
        this.size = val;
    }
    public get dimSize(): number {
   
        return this.size;
    }
    //设置或获取是否显示全周符号
    public set isShowFullWeekSymbol(val: boolean) {
   
        this.isShowFull = val;
    }
    public get isShowFullWeekSymbol(): boolean {
   
        return this.isShowFull;
    }
    //设置或获取公差标注内容
    public set dimToleranceContents(val: toleranceContent[]) {
   
        this.toleranceContents = val;
    }
    public get dimToleranceContents(): toleranceContent[] {
   
        return this.toleranceContents;
    }
    //设置或获取附注上
    public set dimNotesUp(val: string) {
   
        this.notesUp = val;
    }
    public get dimNotesUp(): string {
   
        return this.notesUp;
    }
    //设置或获取附注下
    public set dimNotesDown(val: string) {
   
        this.notesDown = val;
    }
    public get dimNotesDown(): string {
   
        return this.notesDown;
    }
    private getBox(entityArr: McDbEntity[]) {
   
        const mxcad = MxCpp.getCurrentMxCAD();
        let _minPt, _maxPt = null;
        let result;
        entityArr.forEach(entity => {
   
            if (entity instanceof McDbMText) {
   
                // 将ent的文字样式设置为当前文字样式
                const textStyleId = mxcad.getDatabase().getCurrentlyTextStyleId();
                entity.textStyleId = textStyleId;
                entity.reCompute();
                result = MxCADUtility.getTextEntityBox(entity, false);
            } else if (entity instanceof McDbMText) {
   
                entity.reCompute();
                result = MxCADUtility.getTextEntityBox(entity, false);
            } else {
   
                result = entity.getBoundingBox();
            }
            const {
    minPt, maxPt, ret } = result;
            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;
        }
    }
    // 设置标注起点
    public setStartPoint(pt: McGePoint3d) {
   
        this.startPoint = this.turningPoint = this.endPoint = this.dimPoint = pt.clone();
    }
    // 获取标注起点
    public getStartPoint() {
   
        return this.startPoint;
    }
    // 设置标注转折点
    public setTurningPoint(pt: McGePoint3d) {
   
        this.turningPoint = this.endPoint = this.dimPoint = pt.clone();
    }
    // 获取标注转折点
    public getTurningPoint() {
   
        return this.turningPoint;
    }
    // 设置标注终点
    public setEndPoint(pt: McGePoint3d) {
   
        this.endPoint = pt.clone();
    }
    // 获取标注终点
    public getEndPoint() {
   
        return this.endPoint;
    }
    // 获取标注转折点
    public getDimPoint() {
   
        return this.dimPoint;
    }
    // 设置标注终点
    public setDimPoint(pt: McGePoint3d) {
   
        this.dimPoint = this.endPoint = pt.clone();
    }
    // 获取包围盒
    public getBoundingBox(): {
    minPt: McGePoint3d; maxPt: McGePoint3d; ret: boolean; } {
   
        const {
    allEntityArr } = this.getAllEnitty();
        this.getBox(allEntityArr);
        return {
    minPt: this.minPt, maxPt: this.maxPt, ret: true }
    }
AI 代码解读

六、使用方法

6.1.注册MxDbGeometricTolerances实体类

new MxDbGeometricTolerances().rxInit();
AI 代码解读

6.2.绘制形位公差

async function Mx_drawGeometricTolerance() {
   
             // 创建形位公差实体
            const dim = new MxDbGeometricTolerances();
            // 设置公差内容
            dim.dimToleranceContents = [{
   
                "toleranceCode": "b", "tolerance": ["φ","we","<","@"],
                "Benchmark": {
   "b1": [[],[]],"b1": [[],[]],"b1": [[],[]]}
            }];
            dim.isShowFullWeekSymbol = false;
            dim.dimNotesDown = '下标注';
            dim.dimNotesUp = '上标注';
            // 设置标注点
            const getStartPt = new MxCADUiPrPoint();
            getStartPt.setMessage('请设置定位点或直线或圆弧或圆');
            const startPt = await getStartPt.go();
            if (!startPt) return;
            dim.setStartPoint(startPt);           
            // 设置转折点
            const getTurningPt = new MxCADUiPrPoint();
            getTurningPt.setMessage('请设置转折点');
            getTurningPt.setUserDraw((pt, pw) => {
   
                dim.setTurningPoint(pt);
                pw.drawMcDbEntity(dim);
            });
            const turnPt = await getTurningPt.go();
            if (!turnPt) return;
            dim.setTurningPoint(turnPt);           
            // 设置标注位置
            const getDimPt = new MxCADUiPrPoint();
            getDimPt.setMessage('拖动确定标注位置');
            getDimPt.setUserDraw((pt, pw) => {
   
                dim.setDimPoint(pt);
                pw.drawMcDbEntity(dim);
            });
            const dimPt = await getDimPt.go();
            if (!dimPt) return;
            dim.setDimPoint(dimPt);           
            // 设置终点
            const getEndPt = new MxCADUiPrPoint();
            getEndPt.setMessage('拖动确定标注位置');
            getEndPt.setUserDraw((pt, pw) => {
   
                dim.setEndPoint(pt);
                pw.drawMcDbEntity(dim);
            });
            const endPt = await getEndPt.go();
            if (!endPt) return;
            dim.setEndPoint(endPt);   
            // 绘制实体
            const mxcad = MxCpp.getCurrentMxCAD();
            mxcad.drawEntity(dim);
}
AI 代码解读

七、注意事项

  1. 使用前需要确保已正确加载字体文件(cxgdtshp.shx 和 cxgdt.shx)
  2. 形位公差的绘制需要按照正确的顺序设置各个点(起点、转折点、标注点、终点)
  3. 公差内容的设置需要符合规范,包括公差代号、公差值和基准等
  4. 在绘制过程中需要注意坐标系统的正确使用

八、效果演示

在上述介绍中,我们已经实现了形位公差的自定义实体,通过该实体与我们的mxcad项目结合,我们就能够实现更完善的形位公差标注功能。

基础效果演示:
image-20250616151724144.png

根据上述内容可做扩展开发,根据焊接符号特性设置对应的弹框,其示例效果如下:
image-20250616151902572.png

目录
打赏
0
2
2
1
72
分享
相关文章
轻松搭建AI知识问答系统,阿里云PolarDB MCP深度实践
无论是PolarDB MySQL兼容MySQL语法的SQL执行功能,还是其特有的OLAP分析与AI能力,通过MCP协议向LLM开放接口后,显著降低了用户使用门槛,更为未来基于DB-Agent的智能体开发奠定了技术基础
告别低效代码:用对这10个Pandas方法让数据分析效率翻倍
本文将介绍 10 个在数据处理中至关重要的 Pandas 技术模式。这些模式能够显著减少调试时间,提升代码的可维护性,并构建更加清晰的数据处理流水线。
78 3
告别低效代码:用对这10个Pandas方法让数据分析效率翻倍
【Container App】如何测试它是否可以正常发出请求?
本文介绍了如何测试Container App是否可正常发出请求,并查看其出口IP地址。由于Container App的出口IP不固定,建议通过NAT Gateway实现固定IP需求。操作步骤包括使用Console页面的curl命令检测网络请求及IP信息。
Linux命令大全:从入门到精通
日常使用的linux命令整理
279 8
云上玩转Qwen3系列之三:PAI-LangStudio x Hologres构建ChatBI数据分析Agent应用
PAI-LangStudio 和 Qwen3 构建基于 MCP 协议的 Hologres ChatBI 智能 Agent 应用,通过将 Agent、MCP Server 等技术和阿里最新的推理模型 Qwen3 编排在一个应用流中,为大模型提供了 MCP+OLAP 的智能数据分析能力,使用自然语言即可实现 OLAP 数据分析的查询效果,减少了幻觉。开发者可以基于该模板进行灵活扩展和二次开发,以满足特定场景的需求。
Agent 工程师绕不开的必修课:API 网关 vs API 管理
本文探讨了“API管理”与“API网关”的起源、发展及差异,二者分别服务于API生命周期的不同阶段。API网关从流量网关演进至AI网关,承担运行时请求控制;API管理则从接口文档化发展到商业化平台,关注全生命周期治理。两者在实际应用中协同工作,通过分层架构和策略联动实现高效运营。未来,随着大模型应用的兴起,AI网关和MCP Server管理将成为新趋势,推动API技术迈入智能化和服务化的新阶段。
Agent 工程师绕不开的必修课:API 网关 vs API 管理
让AI时代的卓越架构触手可及,阿里云技术解决方案开放免费试用
阿里云推出基于场景的解决方案免费试用活动,新老用户均可领取100点试用点,完成部署还可再领最高100点,相当于一年可获得最高200元云资源。覆盖AI、大数据、互联网应用开发等多个领域,支持热门场景如DeepSeek部署、模型微调等,助力企业和开发者快速验证方案并上云。
1136 39
让AI时代的卓越架构触手可及,阿里云技术解决方案开放免费试用
通义灵码用户说 | 编程智能体+MCP加持,秒查附近蜜雪冰城
通义灵码现已全面支持Qwen3,新增智能体模式,具备自主决策、环境感知、工具使用等能力,可端到端完成编码任务。支持问答、文件编辑、智能体多模式自由切换,结合MCP工具与记忆功能,提升开发效率。AI IDE重构编程流程,让开发更智能高效。
337 20

云原生

+关注
AI助理

你好,我是AI助理

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

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问