0

Here is the problem description:

parse a dxf for all the available entity's (no issues here, straight forward with ezdxf) establish the envelope area and perimeter (done by math not via ezdxf) establish all the contained entities area and perimeter (done by math not via ezdxf) Option 1 parse all the entities for start/end coordinates and match the points, from there figure out the Area and Perimeter

# helper function
def print_entity(line):
    print("LINE on layer: %s\n" % line.dxf.layer)
    print("start point: %s\n" % line.dxf.start)
    print("end point: %s\n" % line.dxf.end)

# iterate over all entities in modelspace
msp = dxf.modelspace()
for line in msp:
    if line.dxftype() == "LINE":
        print(line)
        print_entity(line)

for arc in msp.query('ARC'):
    print('ARC:')

    # Get all attributes
    attribs = arc.dxfattribs()
    for key in arc.dxfattribs():
        print(f'\t{key}: {attribs[key]}')`

Option 1 - while should work seems that is the long and problematic rout to take hence the Option 2

Option 2 parse all the LWPOLYLINE and extract (start, end, bulge) from bulge convert to arc (start_point, end_point, start_angle, end_angle, radius, center (x,y))

No matter what I do I cant extract the bulge information's, should be easy using this available functions:

midpoint, radius, start_angle, end_angle = ezdxf.math.bulge_to_arc(bulge, start, end)
center = ezdxf.math.bulge_center(bulge, start, end)

This iterates trough all LWPOLYLINE

from ezdxf.math import bulge_to_arc, bulge_center
from ezdxf.math.bulge import signed_bulge_radius
from ezdxf.acc.vector import Vec2
import math

# Get the LWPOLYLINE entities from the DXF file
entities = dwg.entities
lwpolylines = [e for e in entities if e.dxftype() == 'LWPOLYLINE']

# Iterate over each LWPOLYLINE entity
for pline in lwpolylines:
    # Get the bulge value, start and end points of each vertex in the polyline
    for x, y, start_width, end_width, bulge in pline:
        print("Start Point: ({}, {})".format(x, y))
        print("End Point: ({}, {})".format(x, y))
        print("Bulge value: ", bulge)
        print("Start Width: ", start_width)
        print("End Width: ", end_width)
        print("\n")

This should extract all the "bulge" informations:

import ezdxf

# Load the DXF file
dwg = ezdxf.readfile("example.dxf")

# Query all LWPOLYLINE entities in the DXF file
for num, line in enumerate(dwg.query('LWPOLYLINE'), start=1):
    print("\n{}. POLYLINE:".format(num))
    
    # Get the points of the LWPOLYLINE
    with line.points() as points:
        for x, y, start_width, end_width, bulge in points:
            if bulge:
                # Convert bulge to arc information
                midpoint, radius, start_angle, end_angle = ezdxf.math.bulge_to_arc(x, y, start_width, end_width, bulge)
                center = ezdxf.math.bulge_center(x, y, start_width, end_width, bulge)
                
                # Print the arc information
                print("\tMidpoint:", midpoint)
                print("\tRadius:", radius)
                print("\tStart Angle:", start_angle)
                print("\tEnd Angle:", end_angle)
                print("\tCenter:", center)

This is the error I get:

/usr/local/lib/python3.8/dist-packages/ezdxf/math/bulge.py in signed_bulge_radius(start_point, end_point, bulge)
    133 ) -> float:
    134     return (
--> 135         Vec2(start_point).distance(Vec2(end_point))
    136         * (1.0 + (bulge * bulge))
    137         / 4.0

src/ezdxf/acc/vector.pyx in ezdxf.acc.vector.Vec2.__cinit__()

TypeError: object of type 'float' has no len()

How would one determine all the Areas and Perimeters available for all CLOSED entities in the DXF file?

CLOSED is defined as two variants: a closed Polyline (LWPOLYLINE) and can have any shape (line, splines and arcs) closed as in each point would start from the previous entity end point (exploded contour)

Is this relevant to my problem? You can access virtual LINE and ARC entities of LWPOLYLINE entities: https://ezdxf.mozman.at/docs/dxfentities/lwpolyline.html#ezdxf.entities.LWPolyline.virtual_entities

Virtual entity means, the ARC and LINE entities are not assigned to any layout.

arc_and_lines = list(pline.virtual_entities())

For approximation (flattening) you can convert the LWPOLYLINE into a Path object: https://ezdxf.mozman.at/docs/path.html

from ezdxf import path
p = path.make_path(pline)
vertices = p.flattening(0.01)

I appreciate any help I can get! Thanks

1 Answers1

0
from ezdxf.math import bulge_to_arc, bulge_center
from ezdxf.math.bulge import signed_bulge_radius
from ezdxf.acc.vector import Vec2
from ezdxf import math

dwg = ezdxf.readfile('your_dxf_file.dxf')
modelspace = dwg.modelspace()

# Get the LWPOLYLINE entities from the DXF file
entities = dwg.entities
lwpolylines = [e for e in entities if e.dxftype() == 'LWPOLYLINE']

# Iterate through the polylines and pass the bulge value to the function
for pline in lwpolylines:
    for index, (x, y, start_width, end_width, bulge) in enumerate(pline):
        start_pline = pline[index+0]
        start_point = (start_pline[0], start_pline[1])
        if index+1 >= len(pline):
            break
        next_pline = pline[index+1]
        end_point = (next_pline[0], next_pline[1])
        # Check if the start & end points are the same
        if start_point == end_point:
            bulge = 0.0 # Set the bulge value to 0
            # Print the updated values
            print("Start Point:", start_point)
            print("End Point:", end_point)
            print("Bulge value: ", bulge)
        elif bulge != 0:
            center_point, start_angle, end_angle, radius = math.bulge_to_arc(start_point, end_point, bulge)
            # Print the updated values
            print("Start Point:", start_point)
            print("End Point:", end_point)
            print("Center Point: {}".format(center_point))
            print("Bulge value: ", bulge)
            print("Start Angle: {}".format(start_angle))
            print("End Angle: {}".format(end_angle))
            print("Radius: {}".format(radius))