实体
图纸所有对象都是从类 McDbObject 继承,该类提供得到对象句柄、ID、对象类型信息等函数。图上可见的对象是从类 McDbEntity 继承,该类提供可见实体的通用属性操作,如线型,图层,文字样式,颜色等函数。
点击 数据库对象 McDbObject、实体对象 McDbEntity 查看详细属性和方法说明。
实体ID和句柄
ID和句柄都用来标识一个对象,ID是一个64位长整型变量,是一个内存地址,访问速度最快,但它每次打开都不一样,如果需要把一个对象的标识存起来,下次又能找到对象,就需要使用句柄,句柄是一个字符串变量,它保证不管什么时候总是不会变化,句柄在DWG图纸中是唯一存在,ID是内存中唯一存在。
我们可以通过 McDbObject 类中提供的 getHandle() 方法获得对象句柄,通过 getObjectID() 方法获得对象ID。
点击 McDbObject.getHandle()、McDbObject.getObjectID() 查看详细属性和方法说明。
// 选择一个目标对象
const getEnt = new MxCADUiPrEntity();
getEnt.setMessage('选择目标对象');
const entVal = await getEnt.go();
if (!entVal.id) return;
// 获取该对象的实体
const ent = entVal.getMcDbEntity();
if(!ent) return;
// 获取对象ID
const entId = ent.getObjectID();
// 获取对象句柄
const sHandle = ent.getHandle();
console.log("对象id", entId);
console.log("对象句柄", sHandle);
实体的类型信息
我们可以通过调用 McDbObject 类中提供的 objectName 属性得到对象的类型名,有了类型名就能判断实体具体是一个什么对象,再调用 dxf0 属性,得到对象的DXF组码的类型名,这个和AutoCAD中的DXF组码是一样,比如直线的类型名为:McDbLine,DXF0组码值: LINE,DXF0组码值可以用来构造集时的类型过滤。
点击 McDbObject.objectName、McDbObject.dxf0 查看详细属性和方法说明。
// 让用户在图上选择一个对象。
const getEnt = new MxCADUiPrEntity();
getEnt.setMessage('选择目标对象');
const entVal = await getEnt.go();
if (!entVal.id) return;
// 获取对象实体
const ent = entVal.getMcDbEntity();
// 得到Dxf0的值。
const sDxfType = ent?.dxf0;
console.log("Dxf0值", sDxfType)
if (ent?.objectName == "McDbLine"){
// ent是一个直线
const line = ent as McDbLine;
// 得到直线开始点
const pt1 = line.startPoint;
// 得到直线结束点
const pt2 = line.endPoint;
console.log(pt1, pt2);
}else if(ent?.objectName == "..."){
// 其他类型
}
可见实体属性
图上可见实体 McDbEntity 的主要属性,有线型,图层,文字样式,颜色,是否可见,显示顺序等。我们可以提取,和修改这些属性。
- 设置实体是否可见
// 隐藏实体
ent.visible = false;
- 修改对象颜色
// 选择目标对象
let getEntity = new MxCADUiPrEntity();
getEntity.setMessage("选择目标对象");
let id = await getEntity.go();
if (!id.isValid()) return;
let ent = id.getMcDbEntity();
if (!ent) return;
// 修改对象颜色
ent.trueColor = new McCmColor(255, 0, 255);
- 修改显示顺序
在用户绘图时,在默认情况下,重叠对象(例如文字、宽多段线和实体填充多边形)通常按其创建次序显示:新创建的对象显示在现有对象前面。本实例演示了如何控制显示顺序,具体实现代码如下:
let ss = new MxCADSelectionSet();
if (!await ss.userSelect("\n选择对象")) return;
//得到当前图上对象的最大,最小显示顺序.
let minmaxOrder = MxCpp.getCurrentDatabase().currentSpace.getMinMaxDrawOrder();
// 把对象放到最上面。
let lOrder = minmaxOrder.maxDrawOrder + 1;
ss.forEach((id) => {
let ent = id.getMcDbEntity();
if (ent) {
ent.drawOrder = lOrder;
}
})
扩展数据
用户可给图纸上的对象设置扩展数据,这些扩展数据可以是用户实际需求的专业数据,扩展数据支持字符串、double、int等类型。每个扩展数据都一个扩展数据名称,每个名称下也可能有多个扩展数据,一个实体可以有多个扩展数据名称,这些扩展数据在内存中是一个链表 MxCADResbuf 来存放的,每个链结代表一个数据,每个链结中字符串数据长度不超过200(由DWG图纸格式确定)。
点击 链表 MxCADResbuf 查看详细属性和方法说明。
// 让用户在图上选择一个对象。
const getEnt = new MxCADUiPrEntity();
getEnt.setMessage('选择目标对象');
const entVal = await getEnt.go();
if (!entVal.id) return;
// 获取对象实体
const ent = entVal.getMcDbEntity();
if(!ent) return;
const xData = new MxCADResbuf();
// 设置扩展数据名称 TestApp
xData.AddString("TestApp",1001);
// 设置字符串数据,DXF组码是1000;
xData.AddString("string data", 1000);
// 设置一个 Long数据,DXF组码是1071
xData.AddLong(77677, 1071);
// 把准备好的数据,写到实体上。
ent.setxData(xData);
编辑实体
我们提供了复制、平移、缩放、变换、镜向、旋转等编辑实体的函数。下面以对实体进行复制平移为例,更多的编辑函数请参考 McDbEntity 。
- 复制平移
import { MxCpp, MxCADUiPrEntity, MxCADUiPrPoint, McGeMatrix3d} from "mxcad";
// 复制平移
export async function test_copyMove() {
// 获取画布实例
const mxcad = MxCpp.App.getCurrentMxCAD();
let copyObj = new MxCADUiPrEntity();//选择复制对象
copyObj.setMessage('请选择需要复制的对象')
let copyObj_id = await copyObj.go();
if (copyObj_id === null) return;
let copyEvent: any = await copyObj_id.getMcDbEntity()//复制的实例对象
if (!copyEvent) return;
let getFristPoint = new MxCADUiPrPoint();
getFristPoint.setMessage('请设定复制基点')
let fristPoint: any = await getFristPoint.go();//基点
if (!fristPoint) return;
let getNextPoint = new MxCADUiPrPoint();
getNextPoint.setMessage('请设置移动长度和方向');
// 动态绘制
getNextPoint.setUserDraw((pt, pw) => {
let evrnt_clone = copyEvent.clone();// 复制实体
let matrix = new McGeMatrix3d();// 创建一个矩阵
matrix.setToTranslation(pt.sub(fristPoint));//设置移动矩阵
evrnt_clone.transformBy(matrix);// 变换实体
pw.drawMcDbEntity(evrnt_clone);// 动态绘制平移后的实体
let pl = new McDbPolyline();// 创建多段线对象
pl.addVertexAt(fristPoint);
pl.addVertexAt(pt);
pw.drawMcDbEntity(pl);// 绘制平移路径
});
let nextPoint = await getNextPoint.go();
if (!nextPoint) return;
// 平移变换
let matrix = new McGeMatrix3d();// 创建一个矩阵
let evrnt_clone = copyEvent.clone();
matrix.clone();
matrix.setToTranslation(nextPoint.sub(fristPoint));//设置移动矩阵
evrnt_clone.transformBy(matrix);// 变换实体
mxcad.drawEntity(evrnt_clone);// 绘制平移后的实体
}
删除实体
我们可以直接通过实体对象或实体对象id调用 McDbEntity 类中的erase() 方法删除实体。
点击McDbEntity.erase() 查看详细属性和方法说明。
// 选择目标对象
let getEntity = new MxCADUiPrEntity();
getEntity.setMessage("选择目标对象");
let id = await getEntity.go();
if (!id.isValid()) return;
id.erase();
// 选择目标对象
let getEntity = new MxCADUiPrEntity();
getEntity.setMessage("选择目标对象");
let id = await getEntity.go();
if (!id.isValid()) return;
// 获取对象实体
const ent = id.getMcDbEntity();
ent.erase();
得到实体坐标
不同的实体它的坐标属性不一样,比如直线就是开始点,和结束点属性,圆的就是中心点坐标和半径属性。所以要得实体的坐标,需要判断对象类型,然后再转换成具体的对象,再读取它的坐标。我们可以通过调用 McDbEntity 类中的 getBoundingBox() 方法得到对象最小外包矩形框坐标。
点击 McDbEntity.getBoundingBox() 查看详细属性和方法说明。
// 让用户在图上选择一个对象。
const getEnt = new MxCADUiPrEntity();
getEnt.setMessage('选择目标对象');
const entVal = await getEnt.go();
if (!entVal.id) return;
// 获取对象实体
const ent = entVal.getMcDbEntity();
if(!ent) return;
// 得到实体的包围盒
const {ret, minPt, maxPt} = ent.getBoundingBox();
if(ret){
// 将显示范围设置为该包围盒的大小
MxCpp.getCurrentMxCAD().zoomW(minPt, maxPt);
}