画对称轴
下面我们将介绍如何利用 mxcad 插件实现在CAD图纸中画对称轴的功能,该功能中用户可设置对称轴长度,点击画布可确定对称轴的起始位置。
功能实现
- 实现自定义对称轴类
为了方便后期管理与修改对称轴设置,我们可以通过继承 McDbCustomEntity 自定义实体类来扩展实现自定义对称轴类。
ts
// 对称轴类
class McDbTestAxisOfSymmetry extends McDbCustomEntity {
// 定义McDbTestAxisOfSymmetry内部的对象
// 对称轴开始点
private startPoint: McGePoint3d = new McGePoint3d();
// 对称轴结束点
private endPoint: McGePoint3d = new McGePoint3d();
// 对称轴标夹点
private midPt: McGePoint3d = new McGePoint3d();
private movePt: McGePoint3d = new McGePoint3d();
private tPoint: McGePoint3d = new McGePoint3d();
// 对称轴标长度
private _axisLength: number = 0;
// 构造函数
constructor(imp?: any) {
super(imp);
}
// 创建函数
public create(imp: any) {
return new McDbTestAxisOfSymmetry(imp)
}
// 获取类名
public getTypeName(): string {
return "McDbTestAxisOfSymmetry";
}
// 读取自定义实体数据
public dwgInFields(filter: IMcDbDwgFiler): boolean {
this.startPoint = filter.readPoint("startPoint").val;
this.endPoint = filter.readPoint("endPoint").val;
this.midPt = filter.readPoint("midPt").val;
this.movePt = filter.readPoint("movePt").val;
this.tPoint = filter.readPoint("tPoint").val;
this._axisLength = filter.readDouble("axisLength").val;
return true;
}
// 写入自定义实体数据
public dwgOutFields(filter: IMcDbDwgFiler): boolean {
filter.writePoint("startPoint", this.startPoint);
filter.writePoint("endPoint", this.endPoint);
filter.writePoint("midPt", this.midPt);
filter.writePoint("movePt", this.movePt);
filter.writePoint("tPoint", this.tPoint);
filter.writeDouble("axisLength", this._axisLength);
return true;
}
// 移动自定义对象的夹点
public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
this.assertWrite();
const l1 = this.startPoint.distanceTo(this.midPt)
const l2 = this.movePt.distanceTo(this.midPt)
const l3 = this.midPt.distanceTo(this.tPoint)
if (iIndex === 0) {
this.startPoint.x += dXOffset;
this.startPoint.y += dYOffset;
this.startPoint.z += dZOffset;
// 重新计算夹点位置
this.getMovePoints(l1, l2, l3);
} else if (iIndex === 1) {
this.endPoint.x += dXOffset;
this.endPoint.y += dYOffset;
this.endPoint.z += dZOffset;
// 重新计算夹点位置
this.getMovePoints(l1, l2, l3);
} else if (iIndex === 2) {
const _midPt = this.midPt.clone();
_midPt.x += dXOffset;
_midPt.y += dYOffset;
_midPt.z += dZOffset;
const line = new McDbLine(this.startPoint, this.endPoint);
const res = line.getClosestPointTo(_midPt, false);
const l = line.getLength()?.val / 2 - this.midPt.distanceTo(this.movePt)
if (res.val && this.startPoint.distanceTo(res.val) <= l) {
const x = res.val.x - this.midPt.x;
const y = res.val.y - this.midPt.y;
const z = res.val.z - this.midPt.z;
this.midPt = res.val;
this.movePt.x += x;
this.movePt.y += y;
this.movePt.z += z;
this.tPoint.x += x;
this.tPoint.y += y;
this.tPoint.z += z;
}
} else if (iIndex === 3) {
const _movePt = this.movePt.clone();
_movePt.x += dXOffset;
_movePt.y += dYOffset;
_movePt.z += dZOffset;
const line = new McDbLine(this.startPoint, this.endPoint);
const res = line.getClosestPointTo(_movePt, false);
const l = res.val?.distanceTo(this.startPoint)
if (l <= line.getLength().val / 2) {
this.movePt = res.val;
}
} else if (iIndex === 4) {
const _tPoint = this.tPoint.clone();
_tPoint.x += dXOffset;
_tPoint.y += dYOffset;
_tPoint.z += dZOffset;
const line = new McDbLine(this.midPt, this.tPoint);
const res = line.getClosestPointTo(_tPoint, true);
this.tPoint = res.val;
}
};
private getMovePoints(l1: number, l2: number, l3: number) {
let startPt, endPt;
if (this.startPoint.x < this.endPoint.x) {
startPt = this.startPoint.clone();
endPt = this.endPoint.clone();
} else {
startPt = this.endPoint.clone();
endPt = this.startPoint.clone();
}
if (this.endPoint.distanceTo(this.startPoint) < (l1 + l2) * 2) {
const v = this.endPoint.sub(this.startPoint).normalize();
endPt = this.startPoint.addvec(v.clone().mult((l1 + l2) * 2));
}
const vec = endPt.sub(startPt).normalize();
this.midPt = startPt.clone().addvec(vec.clone().mult(l1));
this.movePt = this.midPt.clone().addvec(vec.clone().mult(l2));
this.tPoint = this.midPt.clone().addvec(vec.clone().perpVector().mult(l3));
this.endPoint = endPt;
this.startPoint = startPt;
}
// 获取自定义对象的夹点
public getGripPoints(): McGePoint3dArray {
let ret = new McGePoint3dArray()
ret.append(this.startPoint);
ret.append(this.endPoint);
ret.append(this.midPt);
ret.append(this.movePt);
ret.append(this.tPoint);
return ret;
};
// 绘制实体
public worldDraw(draw: MxCADWorldDraw): void {
if (!this._axisLength) this._axisLength = MxFun.screenCoordLong2Doc(10);
this.drawAxiosIcon().forEach(entity => {
draw.drawEntity(entity);
})
const pl = new McDbPolyline();
pl.addVertexAt(this.startPoint);
pl.addVertexAt(this.endPoint);
draw.drawEntity(pl);
}
// 绘制对称轴标
private drawAxiosIcon(): McDbEntity[] {
let startPt, endPt;
if (this.startPoint.x < this.endPoint.x) {
startPt = this.startPoint.clone();
endPt = this.endPoint.clone();
} else {
startPt = this.endPoint.clone();
endPt = this.startPoint.clone();
}
if (this.midPt.distanceTo(this.movePt) == 0) {
this.getMovePoints(this._axisLength / 2, this._axisLength * (5 / 8), this._axisLength);
}
const pt2 = this.midPt.clone().addvec(this.midPt.sub(this.tPoint));
const line1 = new McDbLine(this.tPoint, pt2);
const line2 = line1.clone() as McDbLine;
line2.move(this.midPt, this.movePt);
const _midPt = endPt.clone().subvec(this.midPt.sub(startPt));
const line3 = line1.clone() as McDbLine;
const line4 = line2.clone() as McDbLine;
line3.move(this.movePt, _midPt);
line4.move(this.movePt, _midPt);
return [line1, line2, line3, line4]
}
// 设置对称轴开始点
public setStartPoint(pt: McGePoint3d) {
this.startPoint = pt.clone();
}
// 获取对称轴开始点
public getStartPoint() {
return this.startPoint;
}
// 设置对称轴结束点
public setEndPoint(pt: McGePoint3d) {
this.endPoint = pt.clone()
}
// 获取对称轴结束点
public getEndPoint() {
return this.endPoint;
}
};
- 注册自定义类信息
ts
new McDbTestAxisOfSymmetry().rxInit();
- 编写方法,调用 McDbTestAxisOfSymmetry 自定义对称轴类实现引出标注功能
- 设置对称轴起始点
调用 MxCADUiPrPoint 取点对象设置对称轴的起始点位置。
ts
// 构建对称轴对象
const axis = new McDbTestAxisOfSymmetry();
// 设置对称轴起点
const getPoint1 = new MxCADUiPrPoint();
getPoint1.setMessage('请设置对称轴起点:');
const pt1 = await getPoint1.go();
if (!pt1) return;
axis.setStartPoint(pt1);
// 设置对称轴结束点
const getPoint2 = new MxCADUiPrPoint();
getPoint2.setMessage('请设置对称轴结束点:');
// 动态绘制对称轴
getPoint2.setUserDraw((pt, pw) => {
const _axis = axis.clone() as McDbTestAxisOfSymmetry;
_axis.setEndPoint(pt);
pw.drawMcDbEntity(_axis);
});
const pt2 = await getPoint2.go();
if (!pt2) return;
axis.setEndPoint(pt2);
// 绘制实体
MxCpp.getCurrentMxCAD().drawEntity(axis);
功能实践
实践效果如下:
- 点击画对称轴按钮,执行画对称轴方法
- 点击鼠标左键设置对称轴起始点
- 成功绘制折断线
- 移动对称轴夹点可设置对称轴样式与位置