Tutorial for MultiLeader

New in version 0.18.

A multileader object typically consists of an arrowhead, a horizontal landing (a.k.a. “dogleg”), a leader line or curve, and either a MTEXT object or a BLOCK.

Because of the complexity of the MULTILEADER entity, the factory method add_multileader_mtext() returns a MultiLeaderMTextBuilder instance to build a new entity and the factory method add_multileader_block() returns a MultiLeaderBlockBuilder instance.

Due of the lack of good documentation it’s not possible to support all combinations of MULTILEADER properties with decent quality, so stick to recipes and hints shown in this tutorial to get usable results otherwise, you will enter uncharted territory.

The rendering result of the MULTILEADER entity is highly dependent on the CAD application. The MULTILEADER entity does not have a pre-rendered anonymous block of DXF primitives like the DIMENSION entities, so results may vary from CAD application to CAD application.

MTEXT Quick Draw

Full Python script: mtext_quick_leader.py

The quick_leader() method of a MTEXT - MULTILEADER entity constructs the geometry parameters in reverse manner, starting from a given target point:

DXF document setup:

    doc = ezdxf.new(setup=True)
    # Create a new custom MLEADERSTYLE:
    mleaderstyle = doc.mleader_styles.duplicate_entry("Standard", "EZDXF")
    # The required TEXT style "OpenSans" was created by ezdxf.new() because setup is True:
    mleaderstyle.set_mtext_style("OpenSans")
    msp = doc.modelspace()

Draw a red circle to mark the target point:

    target_point = Vec2(40, 15)
    msp.add_circle(
        target_point, radius=0.5, dxfattribs=GfxAttribs(color=colors.RED)
    )

Create four horizontal placed MULTILEADER entities pointing at the target point, the first segment of the leader line is determined by an angle in this example pointing away from the target point:

    for angle in [45, 135, 225, -45]:
        ml_builder = msp.add_multileader_mtext("EZDXF")
        ml_builder.quick_leader(
            f"angle={angle}°\n2nd text line",
            target=target_point,
            segment1=Vec2.from_deg_angle(angle, 14),
        )
../_images/mleader_mtext_quick_leader_0.png

The content is automatically aligned to the end of the leader line. The first segment is a relative vector to the target point and the optional second segment vector is relative to the end of the first segment. The default connection type is horizontal but can be changed to vertical:

A smaller text size is required:

    mleaderstyle = doc.mleader_styles.duplicate_entry("Standard", "EZDXF")
    mleaderstyle.set_mtext_style("OpenSans")
    mleaderstyle.dxf.char_height = 2.0  # set the default char height of MTEXT

Adding vertical placed MULTILEADER entities:


    for angle in [45, 135, 225, -45]:
        ml_builder = msp.add_multileader_mtext("EZDXF")
        ml_builder.quick_leader(
            f"angle={angle}°\n2nd text line",
            target=target_point,
            segment1=Vec2.from_deg_angle(angle, 14),
            connection_type=mleader.VerticalConnection.center_overline,

This example already shows the limitation caused by different text renderings in various CAD applications. The ezdxf text measurement by matplotlib is different to AutoCAD and BricsCAD and the result is a misalignment of the overline and the leader line.

The DXF file shown in BricsCAD:

../_images/mleader_mtext_quick_leader_1.png

The same DXF file shown with the ezdxf view command (drawing add-on):

../_images/mleader_mtext_quick_leader_2.png

My advice is to avoid vertical placed MULTILEADER entities at all and for horizontal placed MULTILEADER entities avoid styles including an “underline” or an “overline”.

The quick_leader() method is not very customizable for ease of use, but follows the settings of the associated MLeaderStyle.

The following sections show how to have more control when adding MULTILEADER entities.

Create MTEXT Content

Full Python script: mtext_content.py

This section shows how to create a MULTILEADER entity with MTEXT content the manual way with full control over all settings.

For good results the MTEXT alignment should match the leader connection side, e.g. if you attach leaders to the left side also align the MTEXT to the left side, for leaders attached at the right side, align the MTEXT to the right side and if you attach leaders at both sides one side will fit better than the other or maybe a center aligned MTEXT is a good solution, for further details see section MTEXT Alignment.

The first example uses the default connection type of the MLEADERSTYLE “Standard” which is “middle of the top line” for left and right attached leaders. The render UCS for this example is the WCS to keep things simple.

Create a new MULTILEADER entity.

def mtext_content_horizontal_left(filename: str):

Set MTEXT content, text style and alignment.

    doc = ezdxf.new(setup=True)
    msp = doc.modelspace()
    ml_builder = msp.add_multileader_mtext("Standard")
    ml_builder.set_content(
        "Line1\nLine2",

Add the first leader on the left side. The leader points always to the first given vertex and all vertices are given in render UCS coordinates (= WCS in this example).

        style="OpenSans",

More than one vertex per leader can be used:

        alignment=mleader.TextAlignment.left,  # set MTEXT alignment!
    )
    ml_builder.add_leader_line(mleader.ConnectionSide.left, [Vec2(-20, -15)])
    ml_builder.add_leader_line(

The insert point of the build() method is the alignment point for the MTEXT content.

        mleader.ConnectionSide.left,

The “dog leg” settings are defined by the MLEADERSTYLE “Standard”.

../_images/mleader_mtext_left.png

This example shows a leader attached to the right side and the MTEXT aligned to the right side.

    ml_builder = msp.add_multileader_mtext("Standard")
    ml_builder.set_content(
        "Line1\nLine2",
        style="OpenSans",
        alignment=mleader.TextAlignment.right,  # set MTEXT alignment!
    )
    ml_builder.add_leader_line(mleader.ConnectionSide.right, [Vec2(40, -15)])
    ml_builder.build(insert=Vec2(15, 0))
../_images/mleader_mtext_right.png

This example shows two leaders attached to both sides and the MTEXT aligned to the left side, which shows that the right landing gap (space between text and start of vertex) is bigger than the gap on the left size. This is due to the different text size calculations from AutoCAD/BricsCAD and Matplotlib. The longer the text, the greater the error.

    ml_builder = msp.add_multileader_mtext("Standard")
    ml_builder.set_content(
        "Line1\nLine1",
        style="OpenSans",
        alignment=mleader.TextAlignment.left,  # set MTEXT alignment!
    )
    ml_builder.add_leader_line(mleader.ConnectionSide.left, [Vec2(-20, -15)])
    ml_builder.add_leader_line(mleader.ConnectionSide.right, [Vec2(40, -15)])
    ml_builder.build(insert=Vec2(5, 0))
../_images/mleader_mtext_left_right_1.png

A centered MTEXT alignment gives a more even result.

    ml_builder.set_content(
        "First Line\n2. Line",
        style="OpenSans",
        alignment=mleader.TextAlignment.center,  # set MTEXT alignment!
    )
../_images/mleader_mtext_left_right_2.png

But even this has its disadvantages, the attachment calculation is always based on the bounding box of the MTEXT content.

../_images/mleader_mtext_left_right_3.png

MTEXT Connection Types

TODO

MTEXT Alignment

TODO

Create BLOCK Content

TODO

BLOCK Connection Types

TODO

BLOCK Alignment

TODO

BLOCK Scaling

TODO

BLOCK Attributes

TODO

Leader Properties

TODO

Connection Properties

TODO

Polyline Leader

TODO

Spline Leader

TODO

Line Styling

TODO

Arrowheads

TODO

Overall Scaling

TODO

Setup MLEADERSTYLE

TODO