You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Here is an initial version that needs to be finished:
"""build123d import dxfname: import_dxf.pyby: Gumyrdate: November 10th, 2024desc: This python module imports a DXF file as build123d objects.license: Copyright 2024 Gumyr Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License."""importmathimportwarningsimportezdxffrombuild123d.objects_curveimport (
CenterArc,
EllipticalCenterArc,
Line,
Polyline,
SagittaArc,
Spline,
ThreePointArc,
)
frombuild123d.draftingimportArrowfrombuild123d.build_enumsimportAlignfrombuild123d.objects_sketchimportCircle, Polygon, Textfrombuild123d.geometryimportAxis, Pos, TOLERANCE, Vectorfrombuild123d.operations_genericimportscalefrombuild123d.topologyimportShapeList, Vertex, Wiredefprocess_arc(entity):
"""Convert ARC"""start, mid, end=entity.angles(3)
arc_center=Vector(*entity.dxf.center)
radius_vec=Vector(entity.dxf.radius, 0, 0)
pnts= [arc_center+radius_vec.rotate(Axis.Z, a) forain [start, mid, end]]
returnThreePointArc(*pnts)
defprocess_circle(entity):
"""Convert CIRCLE"""returnPos(*entity.dxf.center) *Circle(entity.dxf.radius).edge()
defprocess_ellipse(entity):
"""Convert ELLIPSE"""center=entity.dxf.centermajor_axis=entity.dxf.major_axisx_radius= (major_axis[0] **2+major_axis[1] **2) **0.5y_radius=x_radius*entity.dxf.ratiorotation=math.degrees(math.atan2(major_axis[1], major_axis[0]))
start_angle=math.degrees(entity.dxf.start_param)
end_angle=math.degrees(entity.dxf.end_param)
returnEllipticalCenterArc(
center=center,
x_radius=x_radius,
y_radius=y_radius,
start_angle=start_angle,
end_angle=end_angle,
rotation=rotation,
)
defprocess_insert(entity, doc):
"""Process INSERT by referencing block definition and applying transformations."""block_name=entity.dxf.name# insert_point = (entity.dxf.insert.x, entity.dxf.insert.y, entity.dxf.insert.z)insert_point=entity.dxf.insertscale_factors= (entity.dxf.xscale, entity.dxf.yscale, entity.dxf.zscale)
rotation_angle=entity.dxf.rotation# Retrieve the block definitionblock=doc.blocks.get(block_name)
transformed_entities= []
# Process each entity in the block definitionforblock_entityinblock:
dxftype=block_entity.dxftype()
ifdxftypeinentity_dispatch:
# Process the entity and apply transformationsentity_object=entity_dispatch[dxftype](block_entity)
transformed_entity=scale(entity_object, scale_factors)
transformed_entity=transformed_entity.rotate(Axis.Z, rotation_angle)
transformed_entity.position=insert_pointtransformed_entities.append(transformed_entity)
else:
warnings.warn(f"Unhandled block entity type: {dxftype}")
returnShapeList(transformed_entities)
defprocess_leader(entity):
"""Convert LEADER entity to a Wire with an Arrow at the endpoint."""# Extract the vertices of the LEADER as (x, y) pointsvertices= [Vector(x, y) forx, y, *_inentity.vertices]
# Create a series of lines for the leader segmentsedges= [
Line(start=vertices[i], end=vertices[i+1]) foriinrange(len(vertices) -1)
]
# Calculate arrow size based on leader length or use a defaultleader_length=sum(
Line(start=vertices[i], end=vertices[i+1]).length()
foriinrange(len(vertices) -1)
)
arrow_size= (
leader_length*0.05ifleader_length>0else1.0
) # Default size if leader is very short# Create an arrow at the end of the leaderdirection=vertices[-1] -vertices[-2]
# arrow = Pos(*vertices[-1]) * Arrow(# direction=direction.normalize(), size=arrow_size# )# Return the combined Wire (leader line) and Arrow (arrowhead)# return Wire(edges=edges), arrowreturnWire(edges)
defprocess_line(entity):
"""Convert LINE"""start, end=Vector(*entity.dxf.start), Vector(*entity.dxf.end)
if (start-end).length<TOLERANCE:
warnings.warn("Skipping degenerate LINE")
else:
returnLine(start, end)
defprocess_lwpolyline(entity):
"""Convert LWPOLYLINE"""# (LWPolyline.dxf.elevation is the z-axis value).# Can contain arcsreturnPolyline(*entity.get_points("xy"))
defprocess_point(entity):
"""Convert POINT"""point=entity.dxf.locationreturnVertex(point[0], point[1], point[2])
defprocess_polyline(entity):
"""Convert POLYLINE - a collection of LINE and ARC segments."""edges= []
points=entity.get_points("xyb") # Extracts x, y, and bulge (if available)foriinrange(len(points) -1):
start_point=points[i][:2]
end_point=points[i+1][:2]
bulge=points[i][2] iflen(points[i]) >2else0ifbulge==0:
# Straight segment: create a Lineedge=Line(start_point, end_point)
else:
# Curved segment: create a SagittaArc using the bulge as the sagittasagitta=bulge*math.dist(start_point, end_point) /2edge=SagittaArc(start_point, end_point, sagitta)
edges.append(edge)
returnWire(edges=edges)
defprocess_solid_trace_3dface(entity):
"""Convert filled objects - i.e. Faces"""# Gather vertices as a list of (x, y, z) tuplesvertices= []
foriinrange(4):
# Some entities like SOLID or TRACE may define only 3 vertices, repeating the last one# if the fourth vertex is not defined.try:
vertex=entity.dxf.get(f"v{i}")
vertices.append((vertex.x, vertex.y, vertex.z))
exceptAttributeError:
break# Create the Polygon objectpolygon_obj=Polygon(*vertices)
returnpolygon_objdefprocess_spline(entity):
"""Convert SPLINE"""# Get the control points as a list of (x, y) tuplescontrol_points= [(point[0], point[1]) forpointinentity.control_points]
# Retrieve start and end tangents if availablestart_tangent=entity.dxf.get("start_tangent") # May return None if not definedend_tangent=entity.dxf.get("end_tangent") # May return None if not definedifany(tisNonefortin [start_tangent, end_tangent]):
tangents= ()
else:
tangents= (start_tangent, end_tangent)
# Create the Spline objectspline_obj=Spline(*control_points, tangents=tangents)
returnspline_objdefprocess_text(entity):
"""Convert TEXT"""# Convert alignmentsv_alignment= {0: None, 1: Align.MIN, 2: Align.CENTER, 3: Align.MAX}
h_alignment= {0: Align.MIN, 1: None, 4: Align.CENTER, 2: Align.MAX}
# Extract common attributes for both TEXT and MTEXTposition=entity.dxf.insert# Starting positioncontent= (
entity.dxf.textifentity.dxftype() =="TEXT"elseentity.text
) # Text contentheight= (
entity.dxf.heightifentity.dxftype() =="TEXT"elseentity.dxf.char_height
) # Text heightrotation= (
entity.dxf.rotationifentity.dxftype() =="TEXT"elseentity.dxf.get("rotation", 0)
) # Rotation angle# Create the Text objecttext_obj=Pos(*position) *Text(
content,
font_size=height,
rotation=rotation,
align=(h_alignment[entity.dxf.halign], v_alignment[entity.dxf.valign]),
)
returntext_obj# Dispatch dictionary mapping entity types to processing functionsentity_dispatch= {
"3DFACE": process_solid_trace_3dface,
"ARC": process_arc,
"CIRCLE": process_circle,
"ELLIPSE": process_ellipse,
# "INSERT": process_insert,# "LEADER": process_leader,"LINE": process_line,
"LWPOLYLINE": process_lwpolyline,
# "MTEXT": process_text,"POINT": process_point,
"POLYLINE": process_polyline,
"SOLID": process_solid_trace_3dface,
"SPLINE": process_spline,
"TEXT": process_text,
"TRACE": process_solid_trace_3dface,
}
defimport_dxf(filename: str):
"""Import shapes from a DXF file Args: filename (str): dxf file Raises: DXFStructureError: file not found Returns: ShapeList: build123d objects """try:
doc=ezdxf.readfile(filename)
exceptezdxf.DXFStructureError:
raiseValueError(f"Failed to read {filename}")
build123d_objects= []
# Iterate over all entities in the model spaceforentityindoc.modelspace():
dxftype=entity.dxftype()
print(f"{dxftype=}")
ifdxftypeinentity_dispatch:
new_object=entity_dispatch[dxftype](entity)
print(f"{new_object=}")
ifisinstance(new_object, list):
build123d_objects.extend(new_object)
else:
build123d_objects.append(new_object)
else:
warnings.warn(f"Unable to convert {dxftype}")
returnShapeList(build123d_objects)
The text was updated successfully, but these errors were encountered:
Looking forward to this. Just added this locally to a new project I'm working on, and this properly imported the DXF files exported by ergogen just fine for some case generation work.
Here is an initial version that needs to be finished:
The text was updated successfully, but these errors were encountered: