Skip to content
On this page

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

  1. Enumerate Settings options
ts
// Text alignment
enum textPos {
    // The text is complete
    start,
    // Text line end
    end
}
// Labeling mode
enum markPos {
    // Free labeling
    freeLabeling,
    // Alignment mark
    alignmentMark
}
  1. 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.

ts
// 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;
    }
};
  1. Register custom class information
ts
new McDbTestElevationMark().rxInit();
  1. 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.

ts
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.

ts
// 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.

ts
// 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