局部放大
下面我们将介绍如何利用 mxcad 插件实现在CAD图纸中局部放大的功能,该功能中用户可以自主选择需要放大的区域,并自定义放置放大后图形的位置。局部放大功能能够帮助用户更好的注意到图纸的细节或重点部分,提高快速获取图纸信息的速率。
功能实现
- 实现自定义局部放大标注类
为了方便后期管理与修改标注对象,我们可以通过继承 McDbCustomEntity 自定义实体类来扩展实现局部放大类。我们根据用户框选的放大区域在图纸中调用 MxCADSelectionSet.crossingSelect() 方法获取到目标区域内的所有实体,再通过调用 McDbBlockTableRecord.appendAcDbEntity() 方法将区域内的实体整合为块,然后调用 McDbSpatialFilter.setBoundary() 方法根据自身需求对块的外边框做剪裁。最后根据设置的比例因子对块做缩放。
ts
// 自定义局部放大类
class McDbTestEnlarge extends McDbCustomEntity {
// 定义McDbTestReactArea内部的点对象
// 放大中心点
private center: McGePoint3d = new McGePoint3d();
// 放大范围
private radius: number = 20;
// 放大倍数
private scale: number = 50;
// 插入点
private position: McGePoint3d = new McGePoint3d();
// 构造函数
constructor(imp?: any) {
super(imp);
}
// 创建函数
public create(imp: any) {
return new McDbTestEnlarge(imp)
}
// 获取类名
public getTypeName(): string {
return "McDbTestEnlarge";
}
//设置或获取放大中心点
public set enlargeCenter(val: McGePoint3d) {
this.center = val;
}
public get enlargeCenter(): McGePoint3d {
return this.center;
}
//设置或获取放大范围
public set enlargeRadius(val: number) {
this.radius = val;
}
public get enlargeRadius(): number {
return this.radius;
}
//设置或获取放大倍数
public set enlargeScale(val: number) {
this.scale = val;
}
public get enlargeScale(): number {
return this.scale;
}
// 读取自定义实体数据pt1、pt2
public dwgInFields(filter: IMcDbDwgFiler): boolean {
this.center = filter.readPoint("center").val;
this.position = filter.readPoint("position").val;
this.radius = filter.readDouble("radius").val;
this.scale = filter.readDouble("scale").val;
return true;
}
// 写入自定义实体数据pt1、pt2
public dwgOutFields(filter: IMcDbDwgFiler): boolean {
filter.writePoint("center", this.center);
filter.writePoint("position", this.position);
filter.writeDouble("radius", this.radius);
filter.writeDouble("scale", this.scale);
return true;
}
// 移动自定义对象的夹点
public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
this.assertWrite();
if (iIndex == 0) {
this.center.x += dXOffset;
this.center.y += dYOffset;
this.center.z += dZOffset;
}
else if (iIndex == 1) {
this.position.x += dXOffset;
this.position.y += dYOffset;
this.position.z += dZOffset;
}
};
// 获取自定义对象的夹点
public getGripPoints(): McGePoint3dArray {
let ret = new McGePoint3dArray()
ret.append(this.center);
ret.append(this.position);
return ret;
};
// 绘制实体
public worldDraw(draw: MxCADWorldDraw): void {
const circle = new McDbCircle();
circle.center = this.center;
circle.radius = this.radius;
draw.drawEntity(circle);
const { minPt, maxPt, ret } = circle.getBoundingBox();
if (!ret) return;
let ss = new MxCADSelectionSet();
ss.crossingSelect(minPt.x, minPt.y, maxPt.x, maxPt.y)
const mxcad = MxCpp.getCurrentMxCAD();
let blkTable = mxcad.getDatabase().getBlockTable();
let blkRec = new McDbBlockTableRecord();
let blkRecId = blkTable.add(blkRec);
let blkTableRecord: McDbBlockTableRecord = blkRecId.getMcDbBlockTableRecord() as any;
if (blkTableRecord == null) return;
ss.forEach((id) => {
let ent = id.getMcDbEntity();
if (!ent) return;
let cent = ent.clone() as McDbEntity;
blkTableRecord.appendAcDbEntity(cent);
});
// 设置图块的插入基点,在图形对象的中心位置。
blkTableRecord.origin = new McGePoint3d(this.center.x, this.center.y, 0);
let blkRef = new McDbBlockReference();
blkRef.blockTableRecordId = blkRecId;
blkRef.position = this.position;
const blkRefId = mxcad.drawEntity(blkRef);
blkRef = blkRefId.getMcDbEntity() as McDbBlockReference;
// 设置一个圆做它的剪切边界.
let samplePoints = circle.getSamplePoints(this.radius * 0.00001);
let aryPoint = new McGePoint3dArray();
samplePoints.forEach((val, _type, dxf) => {
if (dxf === 1010) {
const point = new McGePoint3d(val.x, val.y, val.z);
aryPoint.append(point);
}
});
blkRef.createSpatialFilter();
blkRef.setScale(this.scale);
let idSpatialFilter = blkRef.getSpatialFilterId();
let blkFilter: McDbSpatialFilter = idSpatialFilter.getMcDbObject() as any;
blkFilter.setBoundary(aryPoint);
draw.drawEntity(blkRef);
blkRefId.erase();
const vec = this.position.sub(this.center).normalize();
const pt1 = this.center.clone().addvec(vec.mult(this.radius));
const pt2 = this.position.clone().subvec(vec.mult(this.scale));
const line = new McDbLine(pt1, pt2);
draw.drawEntity(line)
}
// 获取position
public setPosition(pt: McGePoint3d) {
this.assertWrite();
this.position = pt.clone();
}
// 获取position
public getPosition() {
return this.position;
}
}
- 注册自定义类信息
ts
new McDbTestEnlarge().rxInit();
- 编写方法,调用 McDbTestEnlarge 自定义局部放大标注类实现局部放大功能
- 获取放大范围
我们可以利用取点对象 MxCADUiPrPoint() 获取放大范围的中心点,再调用 MxCADUiPrDist() 设置放大范围。
ts
// 设置放大中心点
const getPoint = new MxCADUiPrPoint();
getPoint.setMessage('请选择放大中心点');
const point = await getPoint.go();
if (!point) return;
// 设置放大范围
const getDist = new MxCADUiPrDist();
getDist.setMessage('请选择放大范围');
getDist.setBasePt(point);
getDist.setUserDraw((pt, pw) => {
const radius = point.distanceTo(pt);
const circle = new McDbCircle(point.x, point.y, point.z, radius);
pw.drawMcDbEntity(circle);
});
const distVal = await getDist.go();
if (!distVal) return;
const dist = getDist.value();
const mxcad = MxCpp.getCurrentMxCAD();
const circle1 = new McDbCircle(point.x, point.y, point.z, dist);
- 设置放大倍数
ts
// 设置放大倍数
const getAmplifyDist = new MxCADUiPrDist();
getAmplifyDist.setMessage('请设置放大倍数');
getAmplifyDist.setBasePt(point);
getAmplifyDist.setUserDraw((pt, pw) => {
const radius = point.distanceTo(pt);
const circle = new McDbCircle(point.x, point.y, point.z, radius);
pw.drawMcDbEntity(circle);
pw.drawMcDbEntity(circle1);
});
const aDistVal = await getAmplifyDist.go();
if (!aDistVal) return;
const aDist = getAmplifyDist.value();
const scale = aDist / dist
- 指定放大图像位置,并绘制局部放大标注
我们可以利用 MxCADUiPrPoint 取点对象在页面中交互取点。在取点过程中,我们可以通过 MxCADUiPrPoint.setUserDraw() 方法动态绘制对象,使用户更加直观的观察到放大标注的位置变化。
ts
// 设置放大插入点
const getInsertPt = new MxCADUiPrPoint();
getInsertPt.setMessage('请选择放大插入点');
getInsertPt.setUserDraw((pt, pw) => {
const circle = new McDbCircle(pt.x, pt.y, pt.z, aDist);
pw.drawMcDbEntity(circle);
pw.drawMcDbEntity(circle1);
})
const insertPt = await getInsertPt.go();
if (!insertPt) return;
const enlarge = new McDbTestEnlarge();
enlarge.enlargeCenter = point;
enlarge.enlargeRadius = dist;
enlarge.enlargeScale = scale;
enlarge.setPosition(insertPt);
mxcad.drawEntity(enlarge)
功能实践
实践效果如下:
- 点击局部放大按钮,执行局部放大方法
- 选中放大中心点,并确定放大范围
- 设置放大倍数
- 确定标注所在位置
- 成功绘制局部放大标注