明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 611|回复: 3

在线CAD(html预览cad插件)二次开发块表

[复制链接]
发表于 2024-7-17 08:50:36 | 显示全部楼层 |阅读模式
本帖最后由 MxDraw 于 2024-7-17 19:17 编辑

前言

在DWG数据库中,所有图块都存放在块表McDbBlockTable()中,块表中每一条记录称为图块记录对象McDbBlockTableRecord()。图块记录中存放着所有实体数据,用户可以通过改变图块的属性设置来修改其对应着的实体数据。

块表操作

1. 获取当前控件的数据库块表


我们可以通过调用 mxcad 中的 `MxCpp.getCurrentMxCAD()`得到当前的控件, 然后调用控件实例的getDatabase()方法得到数据库实例McDbDatabase() ,在该数据库实例中调用 getBlockTable()方法我们就能获取到块表 McDbBlockTable()

点击[块表 McDbBlockTable()][图块记录对象 McDbLinetypeTableRecord()][数据库实例 McDbDatabase()]查看详细属性和方法说明,参考代码如下:
  1.    import { MxCpp} from "mxcad"
  2.    // 得到当前控件
  3.    let mxcad = MxCpp.App.getCurrentMxCAD();
  4.    // 获取块表
  5.    let blockTable = mxcad.getDatabase().getBlockTable();
复制代码
2. 插入图块

我们可以调用 mxcad 的实例对象中的insertBlock()方法引入插件图块文件得到引用的图块 ID ,最后通过McDbBlockReference()实例化一个 CAD 图块引用实体,设置该实体的blockTableRecordId属性值为引用的图块 ID ,就能实现在图纸中插入目标块。

点击[McObject.insertBlock()]、点击[McDbBlockReference()]查看详细属性和方法说明,参考代码如下:
  1.    import { MxCpp, McDbBlockReference, MxCADUiPrPoint } from "mxcad"
  2.    async function MxTest_InsertBlock(){
  3.        // 目标块文件网络文件路径 且该文件为mxweb格式
  4.        let blkFilePath = new URL("../src/assets/tree.mxweb", import.meta.url).href
  5.        let mxcad = MxCpp.getCurrentMxCAD()
  6.        let blkrecId = await mxcad.insertBlock(blkFilePath, "tree")
  7.        if (!blkrecId.isValid()) return;
  8.        let blkRef = new McDbBlockReference();
  9.        blkRef.blockTableRecordId = blkrecId;
  10.        // 设置块大小
  11.        let box = blkRef.getBoundingBox();
  12.        if (box.ret) {
  13.          let dLen = box.maxPt.distanceTo(box.minPt);
  14.          if (dLen > 0.00001) {
  15.            blkRef.setScale(mxcad.getMxDrawObject().screenCoordLong2Doc(100) / dLen);
  16.          }
  17.        }
  18.        // 设置块基点
  19.        let getPoint = new MxCADUiPrPoint();
  20.        getPoint.setMessage("\指定插入基点");
  21.        getPoint.setUserDraw((v, worldDraw) => {
  22.          blkRef.position = v;
  23.          worldDraw.drawMcDbEntity(blkRef);
  24.        });
  25.        let pt = await getPoint.go();
  26.        if (!pt) return;
  27.        blkRef.position = pt;
  28.        mxcad.drawEntity(blkRef);
  29.    }
复制代码
示例效果如下图:


3. 遍历所有图块

我们可以通过调用块表 McDbBlockTable()中的 getAllRecordId()方法获取所有图块的id,再调用getMcDbBlockTableRecord()方法返回图块记录对象McDbBlockTableRecord() ,得到所有图块记录对象数据,参考代码如下:
  1.    import { MxCpp } from "mxcad"
  2.    let mxcad = MxCpp.App.getCurrentMxCAD();
  3.    let blockTable = mxcad.getDatabase().getBlockTable();
  4.    let aryId = blockTable.getAllRecordId();
  5.    aryId.forEach((id) => {
  6.    let blkRec = id.getMcDbBlockTableRecord();
  7.    if (blkRec === null) return;
  8.        console.log(blkRec);
  9.        console.log("blkRec.name:" + blkRec.name);
  10.        console.log("blkRec.origin:" + blkRec.origin);
  11.    });
复制代码
4. 删除图块

我们得到图块记录对象 McDbBlockTableRecord()后可调用该对象实例的 erase()()方法删除对象,参考代码如下:
  1.    import { MxCpp } from "mxcad"
  2.    let blockTable = MxCpp.getCurrentMxCAD().getDatabase().getBlockTable()
  3.    let blockId = blockTable.get("目标图块名")
  4.    blockId.erase()
  5.    // 更新显示
  6.    mxcad.updateDisplay()
复制代码
5. 查找图块

我们可以调用 McDbBlockTable块表中的has()方法判断当前数据库中,是否存在指定的块名,参考代码如下:
  1.   import { MxCpp } from "mxcad";
  2.    const mxcad = MxCpp.getCurrentMxCAD();
  3.    const dataBase = mxcad.getDatabase();
  4.    const blkTable = dataBase.getBlockTable();
  5.    const res = blkTable.has("目标块名");
  6.    if(res){
  7.        console.log("存在目标块")
  8.    }
复制代码
6. 遍历图块下的所有实体

由于图块中的实体可能是另外的一个图块,因此,在遍历图块下所有实体时我们还需要遍历图块中的图块。下面以选择目标图块输出图块中所有实体的id和对象类型为例,参考代码如下:
  1.    import { MxCADResbuf, MxCADUiPrEntity , McDbBlockReference, McDbBlockTableRecord} from "mxcad";
  2.    // 遍历图块下所有实体
  3.    async function Mx_ForEachBlkEntity(){
  4.        // 选择目标块
  5.        let filter = new MxCADResbuf();
  6.        filter.AddMcDbEntityTypes("INSERT");
  7.        const getBlockEvent = new MxCADUiPrEntity()
  8.        getBlockEvent.setMessage('选择目标块');
  9.        getBlockEvent.setFilter(filter);
  10.        const block_id = await getBlockEvent.go();
  11.        if (!block_id.id) return;
  12.        // 获取块实体
  13.        const blkRef = block_id.getMcDbEntity() as McDbBlockReference;
  14.        // 获取块表记录对象
  15.        let blkRec = blkRef.blockTableRecordId.getMcDbBlockTableRecord();
  16.        // 遍历图块实体
  17.        Mx_ModyfBlockRecordEntity(blkRec)
  18.    }
  19.    function Mx_ModyfBlockRecordEntity(blkRec: McDbBlockTableRecord) {
  20.        // 获取图块中所有实体Id
  21.        blkRec.getAllEntityId().forEach(id => {
  22.            let ent = id.getMcDbEntity();
  23.            // 若实体为图块,则递归遍历
  24.            if (ent instanceof McDbBlockReference) {
  25.                let blkref = ent as McDbBlockReference;
  26.           Mx_ModyfBlockRecordEntity(blkref.blockTableRecordId.getMcDbBlockTableRecord());
  27.            }else{
  28.               // 输出实体id、实体类名
  29.                console.log(id.id,ent.objectName);
  30.            }
  31.        })
  32.    }
复制代码
7. 选择实体做成块

我们可以通过MxCADSelectionSet选择集获取目标实体,再新建McDbBlockTableRecord块表记录对象,将选择的实体对象通过appendAcDbEntity()方法写入记录对象中,最后设置图块的基点、位置等,参考代码如下:
  1.   import { MxCADSelectionSet, MxCpp, McDbBlockTableRecord, McGePoint3d } from "mxcad";
  2.    // 选择实体做成块
  3.    async function MxTest_SelectEntitysToBlock() {
  4.      // 选择要做成块的对象
  5.      let ss = new MxCADSelectionSet();
  6.      if(!await ss.userSelect("选择要做成块的对象:") ) return;
  7.      if(ss.count() == 0) return;
  8.      let mxcad = MxCpp.getCurrentMxCAD();
  9.      // 获取数据库块表
  10.      let blkTable =  mxcad.getDatabase().getBlockTable();
  11.      // 创建新的块表记录对象
  12.      let blkRecId = blkTable.add(new McDbBlockTableRecord());
  13.      let blkTableRecord:McDbBlockTableRecord = blkRecId.getMcDbBlockTableRecord() as any;
  14.      if(blkTableRecord == null) return;
  15.      // 定义新建图块的包围盒最大点和最小点
  16.      let pt1x:any,pt1y:any,pt2x:any,pt2y:any;
  17.      // 遍历选择的实体获取新建图块的包围盒最大点和最小点
  18.      ss.forEach((id)=>{
  19.        let ent = id.getMcDbEntity();
  20.        if(!ent) return;
  21.        let cent = ent.clone() as McDbEntity;
  22.        blkTableRecord.appendAcDbEntity(cent);
  23.        let entBox = ent.getBoundingBox();
  24.        if(entBox.ret){
  25.          if(!pt1x){
  26.            pt1x = entBox.minPt.x;
  27.            pt1y = entBox.minPt.y;
  28.            pt2x = entBox.maxPt.x;
  29.            pt2y = entBox.maxPt.y;
  30.          }
  31.          else {
  32.            if(pt1x > entBox.minPt.x) pt1x= entBox.minPt.x;
  33.            if(pt1y > entBox.minPt.y) pt1y= entBox.minPt.y;
  34.            if(pt2x < entBox.maxPt.x) pt2x= entBox.maxPt.x;
  35.            if(pt2y < entBox.maxPt.y) pt2y= entBox.maxPt.y;
  36.          }
  37.        }
  38.      })
  39.      if(pt1x === undefined){
  40.        return;
  41.      }
  42.      let insertPtx =  pt1x + (pt2x - pt1x) * 0.5;
  43.      let insertPty =  pt1y + (pt2y - pt1y) * 0.5;
  44.      // 设置图块的插入基点,在图形对象的中心位置。
  45.      blkTableRecord.origin = new McGePoint3d(insertPtx,insertPty,0);
  46.      // 设置图块位置
  47.      let blkRef = new McDbBlockReference();
  48.      blkRef.blockTableRecordId = blkRecId;
  49.      blkRef.position = new McGePoint3d(insertPtx,insertPty,0);
  50.      // 绘制图块
  51.      mxcad.drawEntity(blkRef);
  52.      // 删除原实体
  53.      ss.forEach((id)=>{
  54.        let ent = id.getMcDbEntity();
  55.        if(!ent) return;
  56.        ent.erase();
  57.      });
  58.    }
复制代码
示例效果如下:




8. 把一个DWG文件插入到当前文件

我们可以调用 mxcad 对象的 insertBlock()方法把一个DWG文件,插入到图上,指定一个块名,放在块表记录中。下面以在文件中插入一个图章为例,点击[McObject.insertBlock()]查看详细属性和方法说明,参考代码如下:
  1.    import { MxCpp, McDbBlockReference, MxCADUiPrPoint } from "mxcad";
  2.    // 插入图章
  3.    async function MxTest_InsertStamp() {
  4.      // 设置块文件地址
  5.      let baseUrl = "http://localhost:3000/mxcad/"
  6.      if (baseUrl.substring(0, 16) == "http://localhost") {
  7.        baseUrl = getHostUrl() + baseUrl.substring(16);
  8.      }
  9.      let blkFilePath = baseUrl + "stamp.mxweb";
  10.      let mxcad = MxCpp.App.getCurrentMxCAD();
  11.      // 插件图块文件
  12.      let blkrecId = await mxcad.insertBlock(blkFilePath, "stamp");
  13.      if (!blkrecId.isValid()) {
  14.        // 未插入图块
  15.        return;
  16.      }
  17.      // 创建一个新的图块引用实体
  18.      let blkRef = new McDbBlockReference();
  19.      // 设置图块引用实体的图块记录id为blkrecId
  20.      blkRef.blockTableRecordId = blkrecId;
  21.      // 适应图块大小
  22.      let box = blkRef.getBoundingBox();
  23.      if (box.ret) {
  24.        let dLen = box.maxPt.distanceTo(box.minPt);
  25.        if (dLen > 0.00001) {
  26.          blkRef.setScale(mxcad.getMxDrawObject().screenCoordLong2Doc(100) / dLen);
  27.        }
  28.      }
  29.      // 设置图块基点
  30.      let getPoint = new MxCADUiPrPoint();
  31.      getPoint.setMessage("\指定插入基点");
  32.      // 动态绘制图块
  33.      getPoint.setUserDraw((v, worldDraw) => {
  34.        blkRef.position = v;
  35.        worldDraw.drawMcDbEntity(blkRef);
  36.      });
  37.      // 设置图块位置
  38.      let pt = await getPoint.go();
  39.      if (!pt) return;
  40.      blkRef.position = pt;
  41.      // 绘制图块实体
  42.      mxcad.drawEntity(blkRef);
  43.    }
复制代码
示例效果如下:


9. 块属性

AutoCAD中,块属性是将数据附着到块上的标签或标记。我们可以通过新创建一个块引用中的属性定义文字类McDbAttribute来为目标图块添加属性文字。下面以插入一个带有属性文字的图块为例,点击[McDbAttribute]查看详细属性和方法说明,参考代码如下:
  1.   // 在块中插入属性文字 ent:块实体
  2.    let blkRef: McDbBlockReference = ent;
  3.    const blkrecId = blkRef.blockTableRecordId
  4.    // 获取图块记录对象
  5.    let blkRecord: any = blkrecId.getMcDbBlockTableRecord();
  6.    // 获取图块记录中的所有实体对象ID
  7.    let ids = blkRecord.getAllEntityId();
  8.    // 遍历实体类型,添加属性文字
  9.    ids.forEach((id: any, index: any) => {
  10.      if (!id.isKindOf("McDbAttributeDefinition")) return;
  11.      let attribDef = id.getMcDbEntity() as McDbAttributeDefinition;
  12.      let tag = attribDef.tag;
  13.      // 设置属性详情
  14.      let attrib = new McDbAttribute();
  15.      attrib.position = attribDef.position;
  16.      attrib.alignmentPoint = attribDef.alignmentPoint;
  17.      attrib.height = attribDef.height;
  18.      attrib.trueColor = attribDef.trueColor;
  19.      attrib.widthFactor = attribDef.widthFactor;
  20.      attrib.textString = "test" + index;
  21.      attrib.tag = tag;
  22.      attrib.isInvisible = attribDef.isInvisible;
  23.      attrib.transformBy(blkRef.blockTransform);
  24.      attrib = blkRef.appendAttribute(attrib).getMcDbEntity() as McDbAttribute;
  25.      attrib.textStyle = attribDef.textStyle;
  26.      attrib.layer = attribDef.layer;
  27.    })
复制代码
示例效果如下:


10. 遍历块中的属性文字

我们可以调用图块引用实体McDbBlockReference对象中的getAllAttribute()方法获取图块中的所有属性文字。

点击[getAllAttribute()]查看详细属性和方法说明,参考代码如下:
  1.     import { McDbBlockReference, McDbAttribute } from "mxcad"
  2.     // 遍历块中的属性文字 ent:块实体
  3.     let blkRef: McDbBlockReference = ent;
  4.     let aryId = blkRef.getAllAttribute();
  5.     aryId.forEach((id) => {
  6.       let attribt: McDbAttribute = id.getMcDbEntity() as any;
  7.       console.log(attribt.textString);
  8.       console.log(attribt.tag);
  9.     })
复制代码
在线示例

示例项目地址:
[在线CAD梦想画图]








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2024-7-17 17:52:38 | 显示全部楼层
删除块表记录之前不需要遍历全部引用吗?
 楼主| 发表于 2024-7-18 09:29:25 | 显示全部楼层
你有种再说一遍 发表于 2024-7-17 17:52
删除块表记录之前不需要遍历全部引用吗?

删除块表记录后不会影响之前引用的块,只会在块表中删除该块表记录,后续无法再次引用
 楼主| 发表于 2024-7-18 09:38:59 | 显示全部楼层
MxDraw 发表于 2024-7-18 09:29
删除块表记录后不会影响之前引用的块,只会在块表中删除该块表记录,后续无法再次引用

有其他问题,可以加微信18784290597
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-10-18 12:00 , Processed in 0.188312 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表