ezdxf icon indicating copy to clipboard operation
ezdxf copied to clipboard

Result of insert.virtual_entities() different from AutoCAD visualization

Open Nicolas-Weaver-Optimiz opened this issue 2 months ago • 2 comments

Virtual_entities_flip_bug.zip

ezdxf version: '1.4.2' OS: Windows 11

Hello,

I have an issue concerning the virtual_entities function from the insert class. In my dxf plan below, I have two inserts. The first one (at the bottom) has reversed x values compared to the AutoCAD visualisation that I have. However, the second insert has the expected virtual entities.

To Reproduce Here is the python script I have for transforming the data and its visualization:

inserts = msp.query("INSERT")
hatches = []
for insert in inserts:
    virtual_entities = insert.virtual_entities()
    hatches.extend([e for e in virtual_entities if e.dxftype() == "HATCH"])
plot_hatches(hatches)
from ezdxf.entities import LineEdge, ArcEdge, EllipseEdge, SplineEdge
import matplotlib.pyplot as plt

def plot_hatches(hatches):
    fig, ax = plt.subplots()
    for hatch in hatches:
        # Iterate over boundary paths
        for path in hatch.paths:
            for edge in path.edges:
                if isinstance(edge, LineEdge):
                    x = [edge.start[0], edge.end[0]]
                    y = [edge.start[1], edge.end[1]]
                    ax.plot(x, y, color="blue")

                elif isinstance(edge, ArcEdge):
                    arc = list(edge.flattening(distance=0.1))
                    x, y = zip(*arc)
                    ax.plot(x, y, color="red")

                elif isinstance(edge, EllipseEdge):
                    ellipse = list(edge.flattening(distance=0.1))
                    x, y = zip(*ellipse)
                    ax.plot(x, y, color="green")

                elif isinstance(edge, SplineEdge):
                    spline = list(edge.flattening(distance=0.1))
                    x, y = zip(*spline)
                    ax.plot(x, y, color="orange")

    ax.set_aspect("equal")
    plt.show()

Screenshots Image of the obtained result:

Image

Image of the expected result: Image

Thank you for your time.

Nicolas-Weaver-Optimiz avatar Oct 21 '25 17:10 Nicolas-Weaver-Optimiz

When you render the HATCH entity you cannot ignore the OCS (Object Coordinate System).

You can look the Frontend class of the drawing add-on, to see how we render DXF entities.

Links:

  • https://github.com/mozman/ezdxf/blob/master/src/ezdxf/addons/drawing/frontend.py
  • https://github.com/mozman/ezdxf/blob/149013a7f2f5aeb41a8e8df96044635c587acb48/src/ezdxf/addons/drawing/frontend.py#L576

mozman avatar Oct 22 '25 14:10 mozman

Hello back,

Thank you for your frontend tips for plotting.

However I still have the same bug when I look at the coordinates of my drawing.

Here is the original image in the dxf document.

import matplotlib.pyplot as plt
import ezdxf
from ezdxf.addons.drawing import RenderContext, Frontend
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend

file = "C:/Users/optim/Documents/Plans_dxf/Virtual_entities_flip_bug.dxf"
dxf_doc = ezdxf.readfile(file)
msp = dxf_doc.modelspace()

fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])
ctx = RenderContext(dxf_doc)
out = MatplotlibBackend(ax)
Frontend(ctx, out).draw_layout(msp, finalize=True)
ax.set_title("Hatches from modelspace")
Image

When I transform my inserts into hatches using virtual_entities, I obtain this result:

# Convert inserts in virtual entities
inserts = msp.query("INSERT")
hatches = []
for insert in inserts:
    virtual_entities = insert.virtual_entities()
    hatches.extend([e for e in virtual_entities if e.dxftype() == "HATCH"])

# Plot hatches using path edges
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])

for hatch in hatches:
    for path in hatch.paths:
        path_points = [edge.start for edge in path.edges]
        path_points.append(path.edges[-1].end)
        x_points = [point.x for point in path_points]
        y_points = [point.y for point in path_points]
        plt.plot(x_points, y_points)
        print("path_points =", path_points)
plt.show()
Image

We can see that for one of the elements (the blue one), the x coordinates have been flipped along the y axis. Indeed, if we look at the coordinates we have: path_points = [Vec2(-47.33152038086379, 4.993036263367799), Vec2(-47.33152038086331, 624.9930362633677), Vec2(-236.33152038086297, 624.9930362633677), Vec2(-68.7471367213461, 603.5774199228849), Vec2(-47.33152038086379, 4.993036263367799)] Yet, in the original drawing, the x coordinates are positive.

Finally, when we look at the ezdxf display on a empty file, we get the expected result.

empty_doc = ezdxf.new()
for hatch in hatches:
    empty_doc.entitydb.add(hatch)
    new_msp = empty_doc.modelspace()
    new_msp.add_entity(hatch)
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])
ctx = RenderContext(empty_doc)
out = MatplotlibBackend(ax)
Frontend(ctx, out).draw_layout(new_msp, finalize=True)
ax.set_title("Hatches from virtual_entities using draw_layout")
Image

Could it be a double mistake being compensated, or am I missing something?

Nicolas-Weaver-Optimiz avatar Oct 31 '25 10:10 Nicolas-Weaver-Optimiz