Skip to content
On this page

Measuring area (polygon, rectangle)

Here we will introduce how to use the mxcad plug-in to measure the area (polygon, rectangle) in the CAD drawing. In this function, the shape and position of the polygon are determined by the user clicking on each vertex of the target polygon, and the size and position of the rectangle are determined by the user clicking on the measurement Angle of the rectangle. At the same time, the user can customize the location of the annotated text. The measuring area (polygon, rectangle) function can help users quickly grasp the data information of the target object, and facilitate the statistics of the engineering quantity.

Function implementation

  1. Implement custom area annotation class

In order to facilitate later management and annotation modification, We can through inheritance McDbCustomEntity custom entity class to extend the area of annotation classes. Among them, polygons and rectangles are drawn by multi-segment lines in mxcad. Section of the line objects and the corresponding entity class for McDbPolyline, This class provides properties or methods to get or set information about the graphical object, which we can choose to call according to our functional requirements. In the function of measuring area (polygon, rectangle), We can call McDbPolyline.getLength() Method to obtain the length of the multiline object and to call it when the multiline is closed McDbPolyline.getArea() method for area.

Then, we can use McDbMText measurement information text object, the object of the label information on the page.

ts
// Custom area annotation class
class McDbTestAreaComment extends McDbCustomEntity {
    /** Point group */
    private ptArr: McGePoint3d[] = [];
    /** Label point */
    private pt: McGePoint3d;
    /** Word height */
    private height: number = 50;
    /** Convexity number group */
    private dbulges: number[] = [];
    /** Measure whether the object is rectangular */
    private isReactFlag: boolean = false;
    constructor(imp?: any) {
        super(imp);
    }
    public create(imp: any) {
        return new McDbTestAreaComment(imp)
    }
    /** Get class name */
    public getTypeName(): string {
        return "McDbTestAreaComment";
    }
    //Sets or gets the text word height
    public set textHeight(val: number) {
        this.height = val;
    }
    public get textHeight(): number {
        return this.height;
    }
    //Sets or gets whether the measurement object is rectangular
    public set isReact(val: boolean) {
        this.isReactFlag = val;
    }
    public get isReact(): boolean {
        return this.isReactFlag;
    }
    /** Read data */
    public dwgInFields(filter: IMcDbDwgFiler): boolean {
        this.ptArr = filter.readPoints('ptArr').val;
        this.pt = filter.readPoint('pt').val;
        const _dbulges = filter.readString("dbulges").val;
        this.dbulges = _dbulges.split(',').map(Number);
        this.isReactFlag = filter.readLong("isReactFlag").val ? true : false;
        return true;
    }
    /** Write data */
    public dwgOutFields(filter: IMcDbDwgFiler): boolean {
        filter.writePoints("ptArr", this.ptArr);
        filter.writePoint("pt", this.pt);
        const _dbulges = this.dbulges.toString();
        filter.writeString("dbulges", _dbulges);
        filter.writeLong("isReactFlag", this.isReactFlag ? 1 : 0);
        return true;
    }
    /** Moving pinch */
    public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
        this.assertWrite();
        this.ptArr.forEach((point, index) => {
            if (index === iIndex) {
                point.x += dXOffset;
                point.y += dYOffset;
                point.z += dZOffset;
            }
        });
        if (iIndex === this.ptArr.length) {
            this.pt.x += dXOffset;
            this.pt.y += dYOffset;
            this.pt.z += dZOffset;
        }
    };
    /** Grab pinch */
    public getGripPoints(): McGePoint3dArray {
        let ret = new McGePoint3dArray();
        this.ptArr.forEach(point => {
            ret.append(point);
        })
        ret.append(this.pt);
        return ret;
    };
    /** Dynamic rendering */
    public worldDraw(draw: MxCADWorldDraw): void {
        const pl = new McDbPolyline();
        pl.isClosed = true;
        if (this.isReactFlag) {
            // You measure the rectangle, and you get the two corners of the rectangle
            pl.addVertexAt(this.ptArr[0], 0, 0.1, 0.1);
            pl.addVertexAt(new McGePoint3d(this.ptArr[1].x, this.ptArr[0].y), 0, 0.1, 0.1);
            pl.addVertexAt(this.ptArr[1], 0, 0.1, 0.1);
            pl.addVertexAt(new McGePoint3d(this.ptArr[0].x, this.ptArr[1].y), 0, 0.1, 0.1);
        } else {
            // The measurements are polygons
            this.ptArr.forEach((pt, index) => {
                pl.addVertexAt(pt, this.dbulges[index], 0.1, 0.1);
            });
        }
        // Obtain object data information
        const area = pl.getArea().val;
        const length = pl.getLength().val;
        // Constructs a text object
        const text = new McDbMText();
        text.contents = `面积:${area.toFixed(2)}\\P周长:${length.toFixed(2)} `;
        text.attachment = McDb.AttachmentPoint.kMiddleCenter;
        text.location = this.pt;
        text.textHeight = MxFun.screenCoordLong2Doc(this.height);
        // Set annotation color
        text.trueColor = this.trueColor;
        draw.trueColor = this.trueColor;
        // Draw annotation object
        draw.drawEntity(text);
        draw.drawEntity(pl);
    }
    /** Set tag point */
    public setPoint(pt: McGePoint3d) {
        this.assertWrite();
        this.pt = pt.clone();
    }
    /** Increment vertex */
    public addVertex(pt: McGePoint3d, dbulge?: number) {
        this.assertWrite();
        this.ptArr.push(pt.clone());
        this.dbulges.push(dbulge ? dbulge : 0);
    }
    /** Get tag point */
    public getPoint() {
        return this.pt;
    }

}
  1. Register custom class information
ts
new McDbTestAreaComment().rxInit();
  1. Write a method and call McDbTestAreaComment custom area annotation class to achieve the function of measuring area (polygon, rectangle)
  • Measure the polygon area

To measure the polygon area, it is necessary to take points continuously, and take no less than 3 points. We can use MxCADUiPrPoint The point object loops through the drawing to determine the position and size of the polygon to be measured, And through the MxCADUiPrPoint.setKeyWords() Set the keyword list for it, so that users can realize the autonomous undo operation or end the operation in advance, which is convenient for interaction.

ts
// Measuring polygon area
async function Mx_Area() {
    // Polygon vertex value
    const ptArr: McGePoint3d[] = [];
    // Gets the first vertex of the polygon
    const getPt1 = new MxCADUiPrPoint();
    getPt1.setMessage('Please select the first point of the area');
    const pt1 = await getPt1.go();
    if (!pt1) return;
    ptArr.push(pt1);
    // Loop fetch point
    while (true) {
        const getPt = new MxCADUiPrPoint();
        getPt.setMessage('Please select the next point');
        getPt.setKeyWords("[Rollback(B)/End(O)]");
        getPt.setUserDraw((pt, pw) => {
            const draw_pl = new McDbPolyline();
            ptArr.forEach(point => {
                draw_pl.addVertexAt(point, 0, 0.1, 0.1);
            });
            draw_pl.addVertexAt(pt);
            pw.drawMcDbEntity(draw_pl);
        });
        const pt = await getPt.go();
        const key = getPt.keyWordPicked();
        if (key === 'B') {
            // Rollback to the previous fetch point object
            if (ptArr.length > 1) {
                ptArr.pop();
            }
        } else if (key === 'O') {
            // End fetch point
            break;
        } else {
            if (!pt) break;
            ptArr.push(pt);
        }
    };
    // Take at least 3 points of the measurement polygon
    if(ptArr.length < 2) return;
    // Construct area annotation object and set annotation position
    const mxcad = MxCpp.getCurrentMxCAD();
    const area = new McDbTestAreaComment();
    ptArr.forEach((point) => {
        area.addVertex(point, 0);
    });
    const position = new MxCADUiPrPoint();
    position.setMessage('Please select the location marked by area');
    position.setUserDraw((pt, pw) => {
        pw.setColor(0xFF0000)  
        area.setPoint(pt);
        pw.drawMcDbEntity(area);
    })
    const positionPt = await position.go();
    if (!positionPt) return;
    area.setPoint(positionPt);
    area.trueColor = new McCmColor(255,0,0)
    mxcad.drawEntity(area);
}
  • Measure rectangular area

To measure the area of a rectangle, the size and position of the rectangle can be determined by selecting only two corners of the rectangle.

ts
// Rectangular area
async function Mx_ReactArea() {
    // Set the two corners of the measurement rectangle
    const getPt1 = new MxCADUiPrPoint();
    getPt1.setMessage('Select corner point 1 of the rectangle');
    const pt1 = await getPt1.go();
    if (!pt1) return;

    const getPt2 = new MxCADUiPrPoint();
    getPt2.setMessage('Select corner point 2 of the rectangle');
    // Dynamic drawing rectangle
    getPt2.setUserDraw((pt, pw) => {
        const pl = new McDbPolyline();
        pl.isClosed = true;
        pl.addVertexAt(pt1);
        pl.addVertexAt(new McGePoint3d(pt.x, pt1.y));
        pl.addVertexAt(pt);
        pl.addVertexAt(new McGePoint3d(pt1.x, pt.y));
        pw.drawMcDbEntity(pl);
    })
    const pt2 = await getPt2.go();
    if (!pt2) return;
    // Structural area labeling
    const reactArea = new McDbTestAreaComment();
    reactArea.isReact = true;
    reactArea.addVertex(pt1);
    reactArea.addVertex(pt2);
    // Set annotation location
    const getPos = new MxCADUiPrPoint();
    getPos.setMessage('Please set the location of the area label');
    getPos.setUserDraw((pt, pw) => {
        pw.setColor(0xFF0000)
        reactArea.setPoint(pt);
        pw.drawMcDbEntity(reactArea);
    });
    const position = await getPos.go();
    if (!position) return;
    reactArea.setPoint(position);
    // Set annotation color
    reactArea.trueColor = new McCmColor(255, 0, 0)
    MxCpp.getCurrentMxCAD().drawEntity(reactArea);
}

Functional practice

Practical effects are as follows:

  • Click the measurement button to perform the measurement method
  • Left mouse click on canvas to pick up points
  • Command line enter the keyword to execute the corresponding command
  • Click the right mouse button to end the fetching point
  • Adjust the mouse position and click the left button to set the point position
  • The contents of the measurement annotations were successfully drawn