(在线CAD控件)网页CAD实现粗糙度标注的方法

简介: 本文介绍了通过MxCAD二次开发实现机械制图中表面粗糙度符号的标注功能。表面粗糙度符号用于表示零件表面微观不平度,基本形式为三角形,可结合不同修饰(如加横线、小圆等)表达具体加工要求。文章解析了符号含义,并基于McDbCustomEntity类创建自定义实体,实现符号绘制、数据持久化、夹点设置等功能。此外,还提供了用户交互式标注方法,支持根据直线、圆弧或指定角度生成粗糙度标注。最后展示了效果演示及扩展开发示例,便于开发者进一步定制功能。

前言

‌表面粗糙度符号是机械制图中的重要标注符号,用于表示零件表面的微观不平度。它的基本形式是一个三角形,尖端从材料外垂直指向被标注的表面。符号的尖端必须从材料外垂直指向被标注的表面,标注可以注在尺寸界线上、轮廓线上、延长线上或代号中‌。在本篇文章中我们将通过解析表面粗糙度符号,调用mxcad二次开发实现粗糙度标注功能。

表面粗糙度符号解析

image-20250516105056600.png

  1. 基本符号:这些符号代表了表面可以用任何方法获得。它们简洁而直观,是表达设计意图的基础。
  2. 加工方法符号:在基本符号的长边上加上一横线,可以标注相关的加工方法。无论是车削、铣削还是其他任何去除材料的方法,都能通过这些符号清晰地表达出来。
  3. 去除材料方法符号:在基本符号上加上一小圆,表示表面是通过去除材料的方法获得的。这不仅可以是车、铣等传统加工方法,也可以是磨削、抛光等更精细的处理方式。
  4. 相同去除方法符号:如果多个表面具有相同的去除材料方法,可以在基本符号上加上一个小圆,表示这些表面有相同的粗糙度要求。
  5. 保持原供应状况符号:在某些情况下,表面需要保持其原始供应状况,这时可以在基本符号上加上一个小圆,表示这些表面不需要进行任何额外的处理。
  6. 符号与代号的组合:在实际设计中,我们可能会遇到多种符号的组合使用。例如,基本符号加一短线和说明划线,表示表面是通过特定的去除材料方法获得的。

自定义实体实现

根据上述内容中对粗糙度符号的分析,我们可以得到粗糙度标注的核心数据,并根据这些数据通过mxcad里的自定义实体[McDbCustomEntity]实现粗糙度标注实体。

1.基本结构设置

 export class McDbTestRoughness extends McDbCustomEntity {
   
       // 基本属性定义
       private position: McGePoint3d = new McGePoint3d();  // 标注位置
       private textDownString: string[] = ['1.6'];         // 下方文本
       private textUpString: string[] = [];                // 上方文本
       private textLeftString: string = '';                // 左侧文本
       private CornerType: string = '';                    // 角标类型
       private markType: number = 0;                       // 标注类型
       private dimSize: number = 5;                        // 标注尺寸
       private rotation: number = 0;                       // 旋转角度
       private dimHeight: number = 10;                     // 标注高度
       private isSameRequire: boolean = false;             // 是否是相同需求
       private isAddLongLine: boolean = false;             // 是否加长处理
       private isMostSymbols: boolean = false;             // 多数符号
       // 包围盒
       private minPt: McGePoint3d = new McGePoint3d();
       private maxPt: McGePoint3d = new McGePoint3d();
   }

2.构造函数和创建方法

   constructor(imp?: any) {
   
       super(imp);
   }
   public create(imp: any) {
   
       return new McDbTestRoughness(imp);
   }
   public getTypeName(): string {
   
       return "McDbTestRoughness";
   }

3.数据持久化

// 读取自定义实体数据
       public dwgInFields(filter: IMcDbDwgFiler): boolean {
   
           this.position = filter.readPoint("position").val;
           this.minPt = filter.readPoint("minPt").val;
           this.maxPt = filter.readPoint("maxPt").val;
           const textDownStr = filter.readString("textDownStr").val;
           this.textDownString = textDownStr.split(',').filter((item) => item != "");;
           const textUpStr = filter.readString("textUpStr").val;
           this.textUpString = textUpStr.split(',').filter((item) => item != "");;
           this.textLeftString = filter.readString("textLeftStr").val;
           this.CornerType = filter.readString('CornerType').val;
           this.markType = filter.readLong('markType').val;
           this.dimSize = filter.readDouble('dimSize').val;
           this.rotation = filter.readDouble('rotation').val;
           this.dimHeight = filter.readDouble('dimHeight').val;
           this.isSameRequire = filter.readLong('isSameRequire').val == 1 ? true : false;
           this.isAddLongLine = filter.readLong('isAddLongLine').val == 1 ? true : false;
           this.isMostSymbols = filter.readLong('isMostSymbols').val == 1 ? true : false;
           return true;
       }
       // 写入自定义实体数据
       public dwgOutFields(filter: IMcDbDwgFiler): boolean {
   
           filter.writePoint("position", this.position);
           filter.writePoint("maxPt", this.maxPt);
           filter.writePoint("minPt", this.minPt);
           const textDownStr = this.textDownString.join(',');
           const textUpStr = this.textUpString.join(',');
           filter.writeString("textDownStr", textDownStr);
           filter.writeString("textUpStr", textUpStr);
           filter.writeString("textLeftStr", this.textLeftString);
           filter.writeString('CornerType', this.CornerType);
           filter.writeLong('markType', this.markType);
           filter.writeDouble('dimSize', this.dimSize);
           filter.writeDouble('rotation', this.rotation);
           filter.writeDouble('dimHeight', this.dimHeight);
           filter.writeLong('isSameRequire', this.isSameRequire ? 1 : 0);
           filter.writeLong('isAddLongLine', this.isAddLongLine ? 1 : 0);
           filter.writeLong('isMostSymbols', this.isMostSymbols ? 1 : 0);
           return true;
       }

4.设置标注夹点及夹点移动规则

// 移动夹点:标注点即为夹点,若夹点移动则标注点随之移动
   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;
   }

5.绘制标注实体

// 获取所有实体
       public getAllEntity(): McDbEntity[] {
   
           //  根据粗糙度绘制粗糙度形状
           const mxcad = MxCpp.getCurrentMxCAD();
           const entityArr = this.drawShape(this.markType, this.position, this.dimSize, true);
           const pl = entityArr[0] as McDbPolyline;
           const lastPoint = pl.getPointAt(pl.numVerts() - 1).val;
           // 添加左侧文字
           if (this.textLeftString) {
   
               const textLeft = new McDbText();
               textLeft.textString = this.textLeftString;
               textLeft.height = this.dimSize * (9 / 10);
               textLeft.alignmentPoint = textLeft.position = this.position.clone().addvec(McGeVector3d.kYAxis.clone().mult(this.dimSize * (1 / 10))).addvec(McGeVector3d.kXAxis.clone().negate().mult(this.dimSize))
               textLeft.horizontalMode = McDb.TextHorzMode.kTextRight;
               entityArr.push(textLeft)
           }
           // 添加角标
           if (this.CornerType) {
   
               const textCorner = new McDbText();
               textCorner.textString = this.CornerType;
               textCorner.height = this.dimSize * (7 / 10);
               textCorner.alignmentPoint = textCorner.position = this.position.clone().addvec(McGeVector3d.kYAxis.clone().mult(this.dimSize * (3 / 10))).addvec(McGeVector3d.kXAxis.clone().mult(this.dimSize * (9 / 10)))
               textCorner.horizontalMode = McDb.TextHorzMode.kTextLeft;
               entityArr.push(textCorner)
           }
           // 相同要求
           if (this.isSameRequire) {
   
               const cirlce = new McDbCircle();
               cirlce.center = lastPoint.clone();
               cirlce.radius = this.dimSize * (3 / 10);
               entityArr.push(cirlce);
           }
           // 加长横线
           let endX = lastPoint.x;
           // 绘制上标文字
           const height = (7 / 10) * this.dimSize;
           const basePos = lastPoint.clone().addvec(McGeVector3d.kXAxis.clone().mult(this.dimSize * (1 / 2))).addvec(McGeVector3d.kYAxis.clone().mult(this.dimSize * (1 / 5)))
           let basePos_x: number = basePos.x;

           let lineArr: McDbLine[] = []
           if (this.textUpString.length === 1) {
   
               const text = new McDbText();
               text.textString = this.textUpString[0];
               text.height = height;
               text.alignmentPoint = text.position = basePos;

               entityArr.push(text)

               const {
    maxPt } = this.getTextBox(text)

               if (maxPt.x > endX) endX = maxPt.x;
               basePos_x = text.position.x;

           } else if (this.textUpString.length === 2) {
   
               const text1 = new McDbText();
               text1.textString = this.textUpString[0];
               text1.height = height;

               const pos1 = basePos.clone();

               const text2 = new McDbText();
               text2.height = height;
               text2.textString = this.textUpString[1];

               const v = lastPoint.sub(this.position).mult(2 / 3)
               const pos2 = pos1.clone().addvec(v);
               const lastPoint2 = lastPoint.clone().addvec(v);

               text1.alignmentPoint = text1.position = new McGePoint3d(pos2.x, pos1.y);
               text2.alignmentPoint = text2.position = pos2;
               basePos_x = pos2.x;

               const res1 = this.getTextBox(text1)
               const res2 = this.getTextBox(text2)

               const endPt_x = res1.maxPt.x > res2.maxPt.x ? res1.maxPt.x : res2.maxPt.x;
               if (endX < endPt_x) endX = endPt_x + height * 0.3;

               const endPoint2 = new McGePoint3d(endX, lastPoint2.y);
               const line2 = new McDbLine(lastPoint2.x, lastPoint2.y, lastPoint2.z, endPoint2.x, endPoint2.y, endPoint2.y);
               const line3 = new McDbLine(lastPoint.x, lastPoint.y, lastPoint.z, lastPoint2.x, lastPoint2.y, lastPoint2.z);
               lineArr.push(line2);
               entityArr.push(text2);
               entityArr.push(text1);
               entityArr.push(line3);
           }

           // 绘制下标文字
           if (this.textDownString.length) {
   
               const pos = new McGePoint3d(basePos_x, lastPoint.y);
               this.textDownString.forEach((str, index) => {
   
                   const text = new McDbText();
                   text.textString = str;
                   text.height = height;
                   let v: McGeVector3d = new McGeVector3d()
                   v = McGeVector3d.kYAxis.clone().negate().mult(height * (index + 1 + (1 / 6)));
                   text.alignmentPoint = text.position = pos.clone().addvec(v);
                   entityArr.push(text)

                   const res = this.getTextBox(text)

                   endX = endX < res.maxPt.x ? res.maxPt.x : endX;
               });
           };

           if (this.isAddLongLine) {
   
               const endPoint = lastPoint.clone().addvec(McGeVector3d.kXAxis.clone().mult(this.dimSize * 2))
               const line = new McDbLine(lastPoint.x, lastPoint.y, lastPoint.z, endPoint.x, endPoint.y, endPoint.y);
               if (endX < endPoint.x) {
   
                   endX = endPoint.x;
                   entityArr.push(line);
               }
           }

           const endPoint = new McGePoint3d(endX, lastPoint.y)
           const line = new McDbLine(lastPoint.x, lastPoint.y, lastPoint.z, endPoint.x, endPoint.y, endPoint.y);
           entityArr.push(line)
           if (lineArr.length) lineArr.forEach(line => {
   
               line.endPoint.x = endX;
               entityArr.push(line);
           })

           // 多数符号
           const drawArc = (params: McGePoint3d[]) => {
   
               const arc = new McDbArc();
               arc.computeArc(params[0].x, params[0].y, params[1].x, params[1].y, params[2].x, params[2].y);
               entityArr.push(arc)
           }
           if (this.isMostSymbols) {
   
               // 绘制多数符号(两个圆弧+两条直线)
               // 两个圆弧
               const pt = this.position.clone().addvec(McGeVector3d.kYAxis.clone().mult(this.dimSize));
               const basePt = new McGePoint3d(endX, pt.y);

               const radius = this.dimSize * (7 / 5);
               const center1 = basePt.clone().addvec(McGeVector3d.kXAxis.clone().mult(this.dimSize * (7 / 5)));
               const v1 = McGeVector3d.kXAxis.clone().mult(radius);
               const cirlce1_pt1 = center1.clone().addvec(v1.clone().rotateBy(40 * (Math.PI / 180)));
               const cirlce1_pt2 = center1.clone().addvec(v1.clone());
               const cirlce1_pt3 = center1.clone().addvec(v1.clone().rotateBy(320 * (Math.PI / 180)));
               drawArc([cirlce1_pt1, cirlce1_pt2, cirlce1_pt3]);

               const center2 = basePt.clone().addvec(McGeVector3d.kXAxis.clone().mult(this.dimSize * (12 / 5)));
               const cirlce2_pt1 = center2.clone().addvec(v1.clone().rotateBy(140 * (Math.PI / 180)));
               const cirlce2_pt2 = center2.clone().addvec(v1.clone().negate());
               const cirlce2_pt3 = center2.clone().addvec(v1.clone().rotateBy(220 * (Math.PI / 180)));
               drawArc([cirlce2_pt1, cirlce2_pt2, cirlce2_pt3]);

               // 绘制两条直线
               const point = center1.clone().addvec(center2.sub(center1).mult(1 / 3)).addvec(McGeVector3d.kYAxis.clone().negate().mult(this.dimSize * (4 / 5)));
               this.drawShape(2, point, this.dimSize * (4 / 5), false).forEach(ent => {
   
                   entityArr.push(ent)
               });
           };

           this.getBox(entityArr);
           const mat = new McGeMatrix3d();
           const _height = this.maxPt.y - this.minPt.y;
           if (this.dimHeight) {
   
               const scale = this.dimHeight / _height;
               mat.setToScaling(scale, this.position);
           } else {
   
               mat.setToScaling(1, this.position);
           };
           entityArr.forEach(ent => {
   
               ent.transformBy(mat);
           })
           return entityArr
       }
       // 根据粗糙度type类型绘制粗糙度形状
       private drawShape(markType, position, dimSize, flag): McDbEntity[] {
   
           const entityArr: McDbEntity[] = [];
           const v = McGeVector3d.kYAxis.clone().mult(dimSize);
           const vec = McGeVector3d.kXAxis.clone().mult(dimSize * (3 / 5));
           const midPt = position.clone().addvec(v);
           const point1 = midPt.clone().addvec(vec);
           const point2 = midPt.clone().addvec(vec.clone().negate());

           let len = dimSize * (2 / 5);
           if (this.textDownStr.length > 2 && flag) len = dimSize * (1 / 2);
           const point3 = position.clone().addvec(point1.sub(position).mult(len));
           if (markType === 0) {
   
               //  原始样式(倒三角)
               const pl = new McDbPolyline();
               pl.addVertexAt(point1);
               pl.addVertexAt(point2);
               pl.addVertexAt(position);
               pl.addVertexAt(point3);
               entityArr.push(pl)
           } else {
   
               // 不封口三角
               const pl = new McDbPolyline();
               pl.addVertexAt(point2);
               pl.addVertexAt(position);
               pl.addVertexAt(point3);
               entityArr.push(pl)
           }

           if (markType === 1) {
   
               //  带圆:三角形内切圆
               const a = position.distanceTo(point1);
               const b = position.distanceTo(point2);
               const c = point1.distanceTo(point2);
               const s = (a + b + c) / 2;
               const h = position.distanceTo(midPt);
               const A = (c * h) / 2;
               const circle = new McDbCircle();
               circle.radius = A / s;
               circle.center = midPt.clone().addvec(McGeVector3d.kYAxis.clone().negate().mult(circle.radius));
               entityArr.push(circle)
           }

           return entityArr
       }
       // 绘制实体
       public worldDraw(draw: MxCADWorldDraw): void {
   
           const entityArr = this.getAllEntity();
           this.getBox(entityArr);
           entityArr.forEach(item => {
   
               const _clone = item.clone() as McDbEntity;
               if (this.rotation) _clone.rotate(this.position, this.rotation);
               draw.drawEntity(_clone);
           });
       }

6.暴露获取、设置实体内部数据的属性或方法

  // 获取或设置下标文本内容
       public set textDownStr(val: string[]) {
   
           this.textDownString = val;
       }
       public get textDownStr(): string[] {
   
           return this.textDownString;
       }
       // 获取或设置上标文本内容
       public set textUpStr(val: string[]) {
   
           this.textUpString = val;
       }
       public get textUpStr(): string[] {
   
           return this.textUpString;
       }
       // 获取或设置左边文本内容
       public set textLeftStr(val: string) {
   
           this.textLeftString = val;
       }
       public get textLeftStr(): string {
   
           return this.textLeftString;
       }
       // 获取或设置角标类型
       public set rougCornerType(val: string) {
   
           this.CornerType = val;
       }
       public get rougCornerType(): string {
   
           return this.CornerType;
       }
       // 获取或设置标注类型
       public set rougMarkType(val: number) {
   
           this.markType = val;
       }
       public get rougMarkType(): number {
   
           return this.markType;
       }
       // 获取或设置相同要求
       public set isRoungSameRequire(val: boolean) {
   
           this.isSameRequire = val;
           if (val) this.isAddLongLine = true;
       }
       public get isRoungSameRequire(): boolean {
   
           return this.isSameRequire;
       }
       // 获取或设置加长
       public set isAddRougLongLine(val: boolean) {
   
           this.isAddLongLine = val;
       }
       public get isAddRougLongLine(): boolean {
   
           return this.isAddLongLine;
       }
       // 获取或设置多数符号
       public set isShowMostSymbols(val: boolean) {
   
           this.isMostSymbols = val;
       }
       public get isShowMostSymbols(): boolean {
   
           return this.isMostSymbols;
       }
       // 获取或设置粗糙度标注高度
       public set rouDimHeight(val: number) {
   
           this.dimHeight = val;
       }
       public get rouDimHeight(): number {
   
           return this.dimHeight;
       }
       // 设置粗糙度标注位置
       public setPos(pt: McGePoint3d) {
   
           this.position = pt.clone();
       }
       // 获取粗糙度标注位置
       public getPos() {
   
           return this.position;
       }
       // 旋转角度
       public setRotation(angle: number) {
   
           this.rotation = angle
       }
       // 旋转角度
       public getRotation(): number {
   
           return this.rotation
       }
       // 获取包围盒
       public getBoundingBox(): {
    minPt: McGePoint3d; maxPt: McGePoint3d; ret: boolean; } {
   
           const entityArr = this.getAllEntity();
           this.getBox(entityArr);
           return {
    minPt: this.minPt, maxPt: this.maxPt, ret: true }
       }

使用粗糙度标注

根据粗糙度标注于直线、圆弧或圆时标注将垂直于曲线的切线上的位置特点,我们可以通过识别标注点所在的实体类型获取该实体在标注点的切线方向和位置,并以此来确定标注的旋转角度和方向。

// 粗糙度
async function Mx_Roughness() {
   
    const mxcad = MxCpp.getCurrentMxCAD();
    let rotation = 0;
    const roughness = new McDbTestRoughness();
    roughness.rougMarkType = 0;
    roughness.rougCornerType = '';
    const getPos = new MxCADUiPrPoint();
    getPos.setMessage(t('请设置定位点或直线或圆弧或圆'));
    getPos.setUserDraw((pt, pw) => {
   
        roughness.setPos(pt);
        pw.drawMcDbEntity(roughness)
    });
    const pos = await getPos.go();
    let filter = new MxCADResbuf([DxfCode.kEntityType, "LINE,ARC,CIRCLE,LWPOLYLINE"]);
    let objId = MxCADUtility.findEntAtPoint(pos.x, pos.y, pos.z, -1, filter);
    if (objId.isValid()) {
   
        const ent = objId.getMcDbEntity();
        // 拖动确定标注位置
        const getDirect = new MxCADUiPrPoint();
        getDirect.setMessage(t('拖动确定标注位置'));
        getDirect.setUserDraw((pt, pw) => {
   
            const line = ent.clone() as McDbLine;
            const closePt = line.getClosestPointTo(pt, true).val;
            const v = pt.sub(closePt);
            rotation = v.angleTo2(McGeVector3d.kYAxis, McGeVector3d.kNegateZAxis);
            roughness.setPos(closePt);
            roughness.setRotation(rotation);
            pw.drawMcDbEntity(roughness)
        });
        getDirect.setDisableDynInput(true);
        getDirect.disableAllTrace(true);
        const pt = await getDirect.go();
        if (!pt) return;
        mxcad.drawEntity(roughness)
    } else {
   
        roughness.setPos(pos);
        // 指定旋转方向
        const getAngle = new MxCADUiPrAngle();
        getAngle.setBasePt(pos);
        getAngle.setMessage(t('请指定或输入角度'));
        getAngle.setUserDraw((pt, pw) => {
   
            const line = new McDbLine(pt, pos);
            pw.drawMcDbEntity(line);
            const v = pt.sub(pos);
            rotation = v.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
            roughness.setRotation(rotation);
            pw.drawMcDbEntity(roughness)
        });
        let val = await getAngle.go();
        if (!val) return;
        const angle = getAngle.value();
        roughness.setRotation(angle);
        mxcad.drawEntity(roughness);
    }
}

效果演示

在线demo查看地址:https://demo2.mxdraw3d.com:3000/mxcad/

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

根据上述内容可做扩展开发,设置粗糙度弹框,其示例效果如下:
image-20250516131912328.png

相关文章
|
Android开发
eclipse控制台中文输出乱码解决方法
eclipse控制台中文输出乱码解决方法
454 0
|
网络协议 Linux 虚拟化
桥接方式: vmware虚拟机安装的centos7连接外网教程
桥接方式: vmware虚拟机安装的centos7连接外网教程
1566 0
桥接方式: vmware虚拟机安装的centos7连接外网教程
|
5月前
|
人工智能 资源调度 监控
LangChain脚本如何调度及提效?
本文介绍了通过任务调度系统SchedulerX管理LangChain脚本的方法。LangChain是开源的大模型开发框架,支持快速构建AI应用,而SchedulerX可托管AI任务,提供脚本版本管理、定时调度、资源优化等功能。文章重点讲解了脚本管理和调度、Prompt管理、资源利用率提升、限流控制、失败重试、依赖编排及企业级可观测性等内容。同时展望了AI任务调度的未来需求,如模型Failover、Tokens限流等,并提供了相关参考链接。
293 29
LangChain脚本如何调度及提效?
|
5月前
|
存储 人工智能 自然语言处理
flutter3.27接入deepseek-v3跨平台ai流式聊天问答系统
原创基于flutter3.27整合接入deepseek搭建一款高颜值跨平台流式输出ai对话小助手。支持代码高亮、本地会话存储、支持手机端/桌面端显示。 支持markdown代码块高亮、代码块横向滚动、表格边框线、图片100%宽度渲染、图片预览、链接跳转。
332 14
|
5月前
|
存储 人工智能 Cloud Native
【发布实录】云原生+AI,助力企业全球化业务创新
本文介绍了阿里云在云原生与AI结合领域的最新产品发布和技术创新。首先,通过弹性智能的一体化架构,阿里云为AI场景提供了开箱即用的云原生能力,助力企业出海。其次,详细解析了云原生如何助力AI应用构建,包括Function AI平台、GPU极速模式、MCP Server开发托管及AI网关等核心功能。
|
5月前
|
机器学习/深度学习 人工智能 负载均衡
Trae 04.22版本深度解析:Agent能力升级与MCP市场对复杂任务执行的革新
在当今快速发展的AI技术领域,Agent系统正成为自动化任务执行和智能交互的核心组件。Trae作为一款先进的AI协作平台,在04.22版本中带来了重大更新,特别是在Agent能力升级和MCP市场支持方面。本文将深入探讨这些更新如何重新定义复杂任务的执行方式,为开发者提供更强大的工具和更灵活的解决方案。
516 1
|
6月前
|
缓存 运维 安全
官网突然“涉黄”,一场安全漏洞引发的品牌危机
流量劫持是一种常见的黑帽SEO手段,攻击者通过技术手段将用户访问请求重定向到非法网站以获取非法收益。然而,这仅仅是攻击的表象,背后可能隐藏着更大的威胁。一旦攻击者通过漏洞上传Webshell并控制服务器,他们很可能以此为跳板,进一步渗透企业内部网络,窃取敏感数据,例如客户信息、研发图纸或其他关键业务数据。
|
存储 编解码 算法
Transformers 4.37 中文文档(九十三)(4)
Transformers 4.37 中文文档(九十三)
362 1
|
12月前
|
存储 传感器 监控
物联网:物联网卡为什么没有语音功能
物联网卡(IoT SIM卡)主要是为物联网设备设计的,这些设备包括但不限于智能城市传感器、可穿戴设备、工业监控设备、车联网设备等。与普通的消费者SIM卡相比,物联网卡在功能和设计上存在一些显著的区别,其中不包括语音功能是其重要特点之一。以下是物联网卡没有语音功能的几个主要原因: