Mark the elevation
In the following, we will introduce how to use mxcad plug-in to achieve the function of marking height in CAD drawings. In this function, users can set the initial comparison position of height marking, and set the elevation direction, text alignment mode, marking mode, etc., according to the marking requirements.
Function implementation
- Enumerate Settings options
// Text alignment
enum textPos {
// The text is complete
start,
// Text line end
end
}
// Labeling mode
enum markPos {
// Free labeling
freeLabeling,
// Alignment mark
alignmentMark
}
- Implement custom elevation annotation classes
In order to facilitate later management and modification of elevation annotation Settings, We can through inheritance McDbCustomEntity Custom entity classes to extend the implementation of custom elevation annotation classes.
// Elevation marking class
class McDbTestElevationMark extends McDbCustomEntity {
// Define a point object inside the McDbTestElevationMark
// Label point
private markPoint: McGePoint3d = new McGePoint3d();
// Marking point
private directPt: McGePoint3d = new McGePoint3d();
// Mark end point
private endPt: McGePoint3d = new McGePoint3d();
// Word height
private height: number = 0;
// Precision value
private _precisionVal: number = 3;
// Initial altitude
private _initialHeight: number = 0;
// Mark the height
private markHeight: string = "0";
// quadrant
private _quadrant: number = 0;
// Text alignment
private _textPos: number = textPos.end;
// constructor
constructor(imp?: any) {
super(imp);
}
// Create the height function
public create(imp: any) {
return new McDbTestElevationMark(imp)
}
// Get class name
public getTypeName(): string {
return "McDbTestElevationMark";
}
//Sets or gets precision values
public set precisionVal(val: number) {
this._precisionVal = val;
}
public get precisionVal(): number {
return this._precisionVal;
}
//Sets or gets the initial height
public set initialHeight(val: number) {
this._initialHeight = val;
}
public get initialHeight(): number {
return this._initialHeight;
}
//Sets or gets text alignment
public set textPos(val: number) {
this._textPos = val;
}
public get textPos(): number {
return this._textPos;
}
//Sets or gets quadrants
public set quadrant(val: number) {
this._quadrant = val;
}
public get quadrant(): number {
return this._quadrant;
}
// Writes custom entity data
public dwgOutFields(filter: IMcDbDwgFiler): boolean {
filter.writePoint("markPoint", this.markPoint);
filter.writePoint("directPt", this.directPt);
filter.writePoint("endPt", this.endPt);
filter.writeDouble("height", this.height);
filter.writeDouble("height", this.height);
filter.writeDouble("initialHeight", this._initialHeight);
filter.writeLong("precisionVal", this._precisionVal);
filter.writeLong("quadrant", this._quadrant);
filter.writeLong("textPos", this._textPos);
filter.writeString("markHeight", this.markHeight);
return true;
}
// Read from defined entity data
public dwgInFields(filter: IMcDbDwgFiler): boolean {
this.markPoint = filter.readPoint("markPoint").val;
this.directPt = filter.readPoint("directPt").val;
this.endPt = filter.readPoint("endPt").val;
this.height = filter.readDouble("height").val;
this._initialHeight = filter.readDouble("initialHeight").val;
this.markHeight = filter.readString("markHeight").val;
this._precisionVal = filter.readLong("precisionVal").val;
this._textPos = filter.readLong("textPos").val;
this._quadrant = filter.readLong("quadrant").val;
return true;
}
// Moves the pinch point of a custom object
public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
this.assertWrite();
if (iIndex === 0) {
this.markPoint.x += dXOffset;
this.markPoint.y += dYOffset;
this.markPoint.z += dZOffset;
this.directPt.x += dXOffset;
this.directPt.y += dYOffset;
this.directPt.z += dZOffset;
this.endPt.x += dXOffset;
this.endPt.y += dYOffset;
this.endPt.z += dZOffset;
} else if (iIndex === 1) {
const pt = this.directPt.clone();
pt.x += dXOffset;
pt.y += dYOffset;
pt.z += dZOffset;
this.countQuadrant(pt);
} else if (iIndex === 2) {
const point = this.endPt.clone();
const v = this.endPt.sub(this.directPt).normalize().mult(2*this.height);
const pt = this.directPt.clone().addvec(v);
const x = point.x + dXOffset;
if(this._quadrant === 1 || this._quadrant === 4){
x > pt.x ? this.endPt.x += dXOffset:this.endPt.x = pt.x
}else if(this._quadrant === 2 || this._quadrant === 3){
x < pt.x ? this.endPt.x += dXOffset:this.endPt.x = pt.x
}
}
};
// Gets the pinch point of a custom object
public getGripPoints(): McGePoint3dArray {
let ret = new McGePoint3dArray()
ret.append(this.markPoint);
ret.append(this.directPt);
ret.append(this.endPt);
return ret;
};
// Draw entity
public worldDraw(draw: MxCADWorldDraw): void {
// Draw text
const text = new McDbText();
text.height = this.height;
text.textString = this.markHeight;
if (this._textPos === textPos.start) {
text.position = text.alignmentPoint =
(this._quadrant === 3 || this._quadrant === 4) ?
this.endPt.clone().subvec(McGeVector3d.kYAxis.clone().mult(this.height * (5 / 4))) :
this.endPt.clone().addvec(McGeVector3d.kYAxis.clone().mult((1 / 4) * this.height));
} else {
text.position = text.alignmentPoint =
(this._quadrant === 3 || this._quadrant === 4) ?
this.directPt.clone().subvec(McGeVector3d.kYAxis.clone().mult(this.height * (5 / 4))) :
this.directPt.clone().addvec(McGeVector3d.kYAxis.clone().mult((1 / 4) * this.height));
}
// Draw the elevation line
const v = McGeVector3d.kXAxis.clone().mult(this.height * 2);
let pt;
if (this._quadrant === 1 || this._quadrant === 4) {
pt = this.directPt.clone().addvec(v);
if (this._textPos === textPos.start) {
text.horizontalMode = McDb.TextHorzMode.kTextRight;
} else if (this._textPos === textPos.end) {
text.horizontalMode = McDb.TextHorzMode.kTextLeft;
}
} else {
pt = this.directPt.clone().subvec(v);
if (this._textPos === textPos.start) {
text.horizontalMode = McDb.TextHorzMode.kTextLeft;
} else if (this._textPos === textPos.end) {
text.horizontalMode = McDb.TextHorzMode.kTextRight;
}
}
const pl = new McDbPolyline();
pl.addVertexAt(pt);
pl.addVertexAt(this.markPoint);
pl.addVertexAt(this.directPt);
pl.addVertexAt(this.endPt);
draw.drawEntity(pl);
draw.drawEntity(text);
}
// Calculate the quadrant, end point
private countQuadrant(pt?: McGePoint3d) {
const vec = McGeVector3d.kYAxis.clone().mult(this.height);
const v = McGeVector3d.kXAxis.clone().mult(this.height)
if (pt) {
if (pt.y > this.markPoint.y) {
if (pt.x > this.markPoint.x) {
this._quadrant = 1;
} else {
this._quadrant = 2;
}
} else {
if (pt.x > this.markPoint.x) {
this._quadrant = 4;
} else {
this._quadrant = 3;
}
};
}
if (this._quadrant === 1 || this._quadrant === 2) {
const midPt = this.markPoint.clone().addvec(vec);
if (this._quadrant === 1) {
this.directPt = midPt.clone().subvec(v);
} else {
this.directPt = midPt.clone().addvec(v);
}
}
if (this._quadrant === 3 || this._quadrant === 4) {
const midPt = this.markPoint.clone().subvec(vec);
if (this._quadrant === 4) {
this.directPt = midPt.clone().subvec(v);
} else {
this.directPt = midPt.clone().addvec(v);
}
}
const text = new McDbText();
text.height = this.height;
text.textString = this.markHeight;
const id = MxCpp.getCurrentMxCAD().drawEntity(text);
const { minPt, maxPt } = id.getMcDbEntity().getBoundingBox();
id.erase();
const length = maxPt.x - minPt.x + this.height * (7 / 2);
const _v = McGeVector3d.kXAxis.clone().mult(length);
if (this._quadrant === 1 || this._quadrant === 4) {
this.endPt = this.directPt.clone().addvec(_v);
} else {
this.endPt = this.directPt.clone().subvec(_v);
}
}
// Set the location of the annotation point
public setMarkPoint(pt: McGePoint3d) {
this.markPoint = pt.clone();
if (!this.height) this.height = MxFun.screenCoordLong2Doc(15);
this.markHeight = (this.markPoint.y - this._initialHeight).toFixed(this._precisionVal);
!this._quadrant ? this.countQuadrant(this.markPoint) : this.countQuadrant();
}
// Gets the location of the annotated point
public getMarkPoint() {
return this.markPoint;
}
// Set to
public setDirectPt(pt: McGePoint3d) {
this.countQuadrant(pt);
}
// Get to
public getDirectPt() {
return this.directPt;
}
};
- Register custom class information
new McDbTestElevationMark().rxInit();
- Write a method and call the McDbTestElevationMark custom elevation annotation class to achieve the elevation annotation function
- Build the initial McDbTestElevationMark object
The setting of the height precision value in the elevation annotation should be set as a positive integer, that is, the number represents the elevation value accurate to several decimal places; The text alignment must be set to the value in the textPos class enumerated in the preceding step. The annotation alignment must be set to the value in the markPos class enumerated in the previous step. The following example sets the initial value of the elevation annotation directly.
let basePt: McGePoint3d = new McGePoint3d();
const eMark = new McDbTestElevationMark();
// The elevation value is accurate to 3 positions behind the tree
eMark.precisionVal = 3;
// Set the text annotation mode to the beginning of the text
eMark.textPos = textPos.start;
- Set elevation point and elevation direction
Call MxCADUiPrPoint take object elevation annotation set elevation and the elevation direction.
// Get the elevation point
const getPos = new MxCADUiPrPoint();
getPos.setMessage('Please click the elevation point:');
getPos.setUserDraw((pt, pw) => {
const _eMark = eMark.clone() as McDbTestElevationMark;
_eMark.initialHeight = pt.y;
_eMark.setMarkPoint(pt);
pw.drawMcDbEntity(_eMark);
});
const position = await getPos.go();
if (!position) return;
basePt = position.clone();
// Set the initial comparison height
eMark.initialHeight = position.y;
eMark.setMarkPoint(position);
// Set the elevation direction
const getDirectPt = new MxCADUiPrPoint();
getDirectPt.setMessage('Point elevation direction:');
getDirectPt.setUserDraw((pt, pw) => {
const _eMark = eMark.clone() as McDbTestElevationMark;
_eMark.setDirectPt(pt);
pw.drawMcDbEntity(_eMark);
});
const directPt = await getDirectPt.go();
if (!directPt) return;
eMark.setDirectPt(directPt);
const mxcad = MxCpp.getCurrentMxCAD();
mxcad.drawEntity(eMark);
- Continuously draw annotations
With the first marked point drawn as the relative height starting point, the subsequent elevation marks are continuously drawn. During the drawing process, you can determine the position of the subsequent annotation points according to the annotation alignment set in the previous step. If the marking method is aligned, the subsequent elevation points should be aligned with the initial elevation points. If the mark is free, you can set the elevation point position at will.
// Level the alignment line
const line_y = new McDbLine(position.x, 0, 0, position.x, position.y, position.z);
// The annotation alignment is set to free annotation
let _markPos = markPos.freeLabeling;
// Circular annotation
while (true) {
// Continuous access point
const getPoint = new MxCADUiPrPoint();
getPoint.setMessage('Please click on it:');
let point:McGePoint3d = new McGePoint3d();
// Dynamically draw elevation annotations
getPoint.setUserDraw((pt, pw) => {
const _eMark = eMark.clone() as McDbTestElevationMark;
if (_markPos === markPos.alignmentMark) {
point = line_y.getClosestPointTo(pt, true).val
} else {
point = pt.clone()
}
_eMark.setMarkPoint(point);
pw.drawMcDbEntity(_eMark);
// Dynamic drawing of auxiliary lines
const line = new McDbLine(basePt.x, basePt.y, basePt.z, point.x, point.y, point.z);
pw.drawMcDbEntity(line);
});
const nextPt = await getPoint.go();
if (!nextPt) return;
basePt = nextPt.clone();
const _eMark = eMark.clone() as McDbTestElevationMark;
_eMark.setMarkPoint(point);
mxcad.drawEntity(_eMark);
}
Functional practice
Practical effects are as follows:
- Click the elevation marking button to perform the elevation marking method
- Click the left mouse button to set the starting position of the elevation point
- Move the mouse to determine the elevation direction and click the left button to determine
- Continue to move the mouse to continuously click the left button to mark
- Right-click to exit the loop at the end of the take point
- Successfully draw the elevation mark