弧长
下面我们将介绍如何利用 mxcad 插件实现在CAD图纸中测量弧长的功能,该功能中用户点击目标圆弧对象将自动标记出这个圆弧的弧长,同时用户可以自定义选择标注文字的位置。测量弧长功能能够帮助用户快速掌握目标圆弧对象的数据信息,方便统计工程量。
功能实现
- 实现自定义弧长标注类
为了方便后期管理与修改标注,我们可以通过继承 McDbCustomEntity 自定义实体类来扩展实现弧长标注类。其中,在 mxcad 中圆弧对象对应的实体类为 McDbArc ,该类提供了获取或设置圆弧相关信息的属性或方法,我们可以根据我们的功能需求去选择调用。在测量弧长功能中,我们可以调用 McDbArc.getLength() 方法获取圆弧长度。
然后,我们可以利用 McDbText 构造测量信息文本对象,将圆弧的标注信息绘制在页面中。
ts
// 自定义弧长标注类
class McDbTestArcComment extends McDbCustomEntity {
/** 圆弧圆心 */
private center: McGePoint3d = new McGePoint3d();
/** 圆弧半径 */
private radius: number;
/** 圆弧开始角度 */
private startAngle: number;
/** 圆弧结束角度 */
private endAngle: number;
/** 弧线标注点 */
private position: McGePoint3d = new McGePoint3d();
/** 弧线标注文本高度 */
private height: number = 50;
constructor(imp?: any) {
super(imp);
}
public create(imp: any) {
return new McDbTestArcComment(imp)
}
/** 获取类名 */
public getTypeName(): string {
return "McDbTestArcComment";
}
//设置或获取标注圆弧圆心
public set arcCenter(val: McGePoint3d) {
this.center = val.clone();
}
public get arcCenter(): McGePoint3d {
return this.center;
}
//设置或获取标注圆弧半径
public set arcRadius(val: number) {
this.radius = val;
}
public get arcRadius(): number {
return this.radius;
}
//设置或获取标注文本高度
public set textHeight(val: number) {
this.height = val;
}
public get textHeight(): number {
return this.height;
}
//设置或获取标注圆弧起始角度
public set arcStartAngle(val: number) {
this.startAngle = val;
}
public get arcStartAngle(): number {
return this.startAngle;
}
public set arcEndAngle(val: number) {
this.endAngle = val;
}
public get arcEndAngle(): number {
return this.endAngle;
}
/** 读取数据 */
public dwgInFields(filter: IMcDbDwgFiler): boolean {
this.position = filter.readPoint('position').val;
this.center = filter.readPoint('center').val;
this.startAngle = filter.readDouble('startAngle').val;
this.endAngle = filter.readDouble('endAngle').val;
this.radius = filter.readDouble('radius').val;
this.height = filter.readDouble('textHeight').val;
return true;
}
/** 写入数据 */
public dwgOutFields(filter: IMcDbDwgFiler): boolean {
filter.writePoint("position", this.position);
filter.writePoint("center", this.center);
filter.writeDouble("startAngle", this.startAngle);
filter.writeDouble("endAngle", this.endAngle);
filter.writeDouble("radius", this.radius);
filter.writeDouble("textHeight", this.height);
return true;
}
/** 移动夹点 */
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;
};
// 绘制标注样式线段
private drawLine(pt1:McGePoint3d, pt2:McGePoint3d):any{
const vec = pt2.sub(pt1).normalize().mult(MxFun.screenCoordLong2Doc(this.height*0.4));
const _pt = pt2.clone().addvec(vec);
const _ptClone = pt2.clone().subvec(vec);
const line = new McDbLine(_pt, _ptClone)
line.rotate(pt2,Math.PI/4);
return {line, pt:_pt};
}
private pt1:McGePoint3d
private pt2:McGePoint3d
private dbulge:number
/** 动态绘制 */
public worldDraw(draw: MxCADWorldDraw): void {
// 获取测量目标圆弧基础信息
const arc = new McDbArc();
arc.center = this.center;
arc.startAngle = this.startAngle;
arc.endAngle = this.endAngle;
arc.radius = this.radius;
const length = arc.getLength().val;
const startPt = arc.getPointAtDist(0).val;
const endPt = arc.getPointAtDist(length).val;
// 构造标注圆弧长度文本信息
const lText = new McDbText();
lText.textString = `${length.toFixed(2)}`;
lText.height = MxFun.screenCoordLong2Doc(this.height);
lText.horizontalMode = McDb.TextHorzMode.kTextCenter;
lText.position = lText.alignmentPoint = this.position;
// 弧线偏移
const closePt = arc.getClosestPointTo(this.position, true).val;
const dist = closePt.distanceTo(this.position);
arc.offsetCurves(dist, this.position).forEach(obj => {
const offsetEnt = obj.clone() as McDbArc;
const length = offsetEnt.getLength().val;
this.pt1 = offsetEnt.getPointAtDist(0).val;
this.pt2 = offsetEnt.getPointAtDist(length).val;
const midPt = offsetEnt.getPointAtDist(length / 2).val;
this.dbulge = MxCADUtility.calcBulge(this.pt1, midPt, this.pt2).val;
})
// 绘制标注样式
const pl = new McDbPolyline();
pl.addVertexAt(this.pt1, this.dbulge);
pl.addVertexAt(this.pt2);
// 调整文本角度
const angle = this.pt1.sub(this.pt2).angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
lText.rotation = angle === Math.PI ? 0 : angle;
const { line:line1, pt:_pt1 } = this.drawLine(startPt, this.pt1);
const { line:line2, pt:_pt2 } = this.drawLine(endPt, this.pt2);
pl.trueColor = lText.trueColor = line1.trueColor = line2.trueColor = this.trueColor;
draw.drawEntity(pl);
draw.drawEntity(lText);
draw.drawEntity(line1);
draw.drawEntity(line2);
draw.drawEntity(new McDbLine(startPt, _pt1))
draw.drawEntity(new McDbLine(endPt, _pt2))
}
/** 设置标注点 */
public setPosition(pt: McGePoint3d) {
this.assertWrite();
this.position = pt.clone();
}
/** 获取标注点 */
public getPoint() {
return this.position;
}
}
- 注册自定义类信息
ts
new McDbTestArcComment().rxInit();
- 编写方法,调用 McDbTestArcComment 自定义弧长标注类实现测量弧长功能
- 获取目标圆弧对象,得到相关数据信息
我们可以利用选择实体对象 MxCADUiPrEntity() 根据用户鼠标点击的坐标得到对应的实体,其中我们需要只选择圆弧对象,因此,我们再调用 MxCADResbuf() 为选择实体对象设置过滤器来过滤出目标实体。
ts
// 选择实体对象
const getEnt = new MxCADUiPrEntity();
// 设置提示信息
getEnt.setMessage('请选择一条弧线');
// 设置过滤器
const filter = new MxCADResbuf([DxfCode.kEntityType, "ARC"]);
getEnt.setFilter(filter);
// entId过滤选择后的圆实体对象ID
const entId = await getEnt.go();
if (!entId.id) return;
// 获取圆弧相关信息
const arc = entId.getMcDbEntity() as McDbArc;
const mArc = new McDbTestArcComment();
mArc.arcCenter = arc.center;
mArc.arcStartAngle = arc.startAngle;
mArc.arcEndAngle = arc.endAngle;
mArc.arcRadius = arc.radius;
- 指定标注点并绘制弧长标注对象
我们可以利用 MxCADUiPrPoint 取点对象在页面中交互取点。在取点过程中,我们可以通过 MxCADUiPrPoint.setUserDraw() 方法动态绘制标注对象,使用户更加直观的观察到标注对象的位置变化。
ts
// 设置取点对象
const getPos = new MxCADUiPrPoint();
// 设置提示信息
getPos.setMessage("请指定尺寸线位置");
// 动态绘制
getPos.setUserDraw((pt, pw) => {
pw.setColor(0xFF0000);
mArc.setPosition(pt);
pw.drawMcDbEntity(mArc)
});
const position = await getPos.go();
if (!position) return;
// 设置标注文本位置
mArc.setPosition(position);
// 设置弧长标注对象颜色
mArc.trueColor = new McCmColor(0xFF000000);
// 绘制弧长圆标注对象
const mxcad = MxCpp.getCurrentMxCAD();
mxcad.drawEntity(mArc);
功能实践
实践效果如下:
- 点击弧长按钮,执行测量弧长方法
- 选中目标圆弧对象
- 设置标注点位置
- 成功绘制测量标注内容