Search code examples
pythonezdxf

extract .dxf data using ezdxf to add to a pandas dataframe


The end goal is to extract the text contained on a specific layer, inside of a named view, from the model space. I have the layer restriction (the text in yellow for visual), but I can't seem to figure out the syntax (if possible) to limit the query to either items inside one of the named views, or within a bounding box that I define to match the named view (orange box). The text being queried is single text. It is (and will always be) an exploded table. Each text item has a unique .insert value.

enter image description here

enter image description here

Ultimately this above mentioned query loop would be put inside a loop to iterate over all named views (bounding box) inside of the model space. Each of the iterations creating a unique list containing the query results. The list would then be input into a pandas dataframe for further manipulations.

import ezdxf

filepath = "C:/MBS_JOBS-16/8741-22/8741-22_(DTL).dxf"
doc = ezdxf.readfile(filepath)
msp = doc.modelspace()

ls = []
for e in msp.query('TEXT MTEXT[layer=="text"]'):
    ls.append(e.dxf.text)

print(ls)

Solution

  • The ezdxf package does not have a feature for selecting entities based on location and size, but a bounding box based implementation is relatively easy.

    It is important to know that bounding boxes of text based entities (TEXT, MTEXT) are inaccurate because matplotlib (used by ezdxf to render text) renders TTF fonts differently than AutoCAD.

    I created an example DXF file with 6 views, called "v1", "v2", ...: view-example

    The following code prints the the content of view "v1": ["Text1a", "Text1b"]

    import ezdxf
    from ezdxf.math import BoundingBox, Vec2
    from ezdxf import bbox
    
    
    def get_view_box(view):
        center = Vec2(view.dxf.center)
        size = Vec2(view.dxf.width, view.dxf.height)
        bottom_left = center - (size / 2)
        top_right = center + (size / 2)
        return BoundingBox([bottom_left, top_right])
    
    
    doc = ezdxf.readfile("views.dxf")
    msp = doc.modelspace()
    
    view = doc.views.get("v1")
    view_box = get_view_box(view)
    
    for e in msp.query("TEXT MTEXT"):
        text_box = bbox.extents([e])  # expects a list of entities!
        if view_box.contains(text_box):
            print(e.dxf.text)