Extrude DXF which has a lot of details

grindcoretm
Explorer

Extrude DXF which has a lot of details

grindcoretm
Explorer
Explorer

Hello, please help me solve the problem. I'm not a programmer, and I tried to hire 3 freelancers but no one could do what I needed.

This is all I could implement using the script in the ChatGPT.

I need the script to extrude individual parts in the DXF file.

I can't figure out how to specify the definition and extrusion of profiles. I have a lot of similar work and would like to automate it. I really ask you to help me solve this problem and am happy to reward you for your help!

Profiles in DXF what need to extrude.

Screenshot_1.png

What i get after run script :
Screenshot_5.png

How can this be done correctly and is it possible?
Don't pay attention to the other DXF in the code, everything is fine with them while working.
Here my code :

 

import adsk.core, adsk.fusion, adsk.cam, traceback, os

def import_dxf(file_path, root_comp):
    app = adsk.core.Application.get()
    import_manager = app.importManager

    if not os.path.isfile(file_path):
        raise RuntimeError(f"File not found: {file_path}")

    dxf_options = import_manager.createDXF2DImportOptions(file_path, root_comp.xYConstructionPlane)

    try:
        # Import the DXF file into the current design
        import_manager.importToTarget(dxf_options, root_comp)
        # Return the last sketch added to the root component
        sketch = root_comp.sketches.item(root_comp.sketches.count - 1)
    except RuntimeError as e:
        raise RuntimeError(f"Failed to import DXF file '{file_path}': {e}")
    except Exception as e:
        raise RuntimeError(f"Unexpected error while importing DXF file '{file_path}': {e}")

    return sketch

def perform_extrusion(sketch, distance, operation):
    app = adsk.core.Application.get()
    design = app.activeProduct
    root_comp = design.rootComponent

    # Get all profiles
    profiles = sketch.profiles
    if profiles.count == 0:
        raise RuntimeError("No profiles found in the sketch.")
    
    extrudes = root_comp.features.extrudeFeatures

    for i in range(profiles.count):
        profile = profiles.item(i)
        
        # Create an extrusion input
        ext_input = extrudes.createInput(profile, adsk.fusion.FeatureOperations.CutFeatureOperation if operation == 'cut' else adsk.fusion.FeatureOperations.JoinFeatureOperation)
        
        # Define the extent of the extrusion (distance in mm)
        distance_value = adsk.core.ValueInput.createByReal(distance)
        ext_input.setDistanceExtent(False, distance_value)
        
        # Create the extrusion
        extrude = extrudes.add(ext_input)

def combine_occurrences(root_comp):
    app = adsk.core.Application.get()
    design = app.activeProduct
    root_comp = design.rootComponent

    # Collect all occurrences
    all_occurrences = root_comp.allOccurrences

    # Create a collection to store all bodies
    all_bodies = adsk.core.ObjectCollection.create()

    # Iterate through each occurrence and collect its bodies
    for occurrence in all_occurrences:
        component = occurrence.component
        bodies = component.bRepBodies
        for body in bodies:
            all_bodies.add(body)

    if all_bodies.count < 2:
        raise RuntimeError("Not enough bodies to combine.")

    # Use the first body as the target and the rest as tools
    target_body = all_bodies.item(0)
    tool_bodies = adsk.core.ObjectCollection.create()
    for i in range(1, all_bodies.count):
        tool_bodies.add(all_bodies.item(i))

    # Create a combine feature input
    combine_features = root_comp.features.combineFeatures
    combine_input = combine_features.createInput(target_body, tool_bodies)

    # Set the operation type
    combine_input.operation = adsk.fusion.FeatureOperations.JoinFeatureOperation

    # Create the combine feature
    combine_feature = combine_features.add(combine_input)

def save_as_stl(output_path, filename):
    app = adsk.core.Application.get()
    design = app.activeProduct
    export_manager = design.exportManager
    stl_options = export_manager.createSTLExportOptions(design.rootComponent)
    stl_options.meshRefinement = adsk.fusion.MeshRefinementSettings.MeshRefinementHigh
    stl_options.filename = os.path.join(output_path, filename + '.stl')
    
    try:
        export_manager.execute(stl_options)
    except RuntimeError as e:
        raise RuntimeError(f"Failed to export STL: {e}")

def main():
    app = adsk.core.Application.get()
    ui = app.userInterface

    project_path = r"C:\Cuts"  # Use raw string to avoid escape issues
    output_path = r"C:\Cuts"  # Use raw string to avoid escape issues
    if not os.path.exists(output_path):
        os.makedirs(output_path)

    file_paths = [
        ("3mm.dxf", 0.3, 'join'),
        ("7mm.dxf", 0.7, 'join'),
        ("10mm.dxf", 1.0, 'join'),
        ("cut.dxf", 1.2, 'cut'),
        ("stamp.dxf", 0.8, 'join'),
        ("support.dxf", 0.3, 'join')
    ]

    design = app.activeProduct
    root_comp = design.rootComponent

    for file_name, distance, operation in file_paths:
        file_path = os.path.join(project_path, file_name)
        try:
            sketch = import_dxf(file_path, root_comp)
            perform_extrusion(sketch, distance, operation)
        except RuntimeError as e:
            ui.messageBox(f"Failed to import or process DXF file '{file_name}': {e}")
            continue
        except Exception as e:
            ui.messageBox(f"Unexpected error: {e}")
            continue

    try:
        combine_occurrences(root_comp)
        save_as_stl(output_path, os.path.basename(project_path))
        ui.messageBox('Successfully imported, processed, and saved the STL file.')
    except RuntimeError as e:
        ui.messageBox(f"Failed to save STL: {e}")

try:
    main()
except:
    app = adsk.core.Application.get()
    ui = app.userInterface
    ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 



 
0 Likes
Reply
411 Views
2 Replies
Replies (2)

grindcoretm
Explorer
Explorer

I was able to create these as separate bodies. Now the question is how to make it so that when the body is extruded and then when the script extrudes the next bodies and if they intersect with the one that has already been created, they should be cut out or deleted.

I hope I expressed my thoughts correctly, please help me solve this.

Screenshot_10.png

 

import adsk.core, adsk.fusion, adsk.cam, traceback, os

def import_dxf(file_path, root_comp):
    app = adsk.core.Application.get()
    import_manager = app.importManager

    if not os.path.isfile(file_path):
        raise RuntimeError(f"File not found: {file_path}")

    dxf_options = import_manager.createDXF2DImportOptions(file_path, root_comp.xYConstructionPlane)

    try:
        # Import the DXF file into the current design
        import_manager.importToTarget(dxf_options, root_comp)
        # Return the last sketch added to the root component
        sketch = root_comp.sketches.item(root_comp.sketches.count - 1)
    except RuntimeError as e:
        raise RuntimeError(f"Failed to import DXF file '{file_path}': {e}")
    except Exception as e:
        raise RuntimeError(f"Unexpected error while importing DXF file '{file_path}': {e}")

    return sketch

def is_outer_profile(profile):
    for loop in profile.profileLoops:
        if loop.isOuter:
            return True
    return False

def filter_outer_profiles(profiles):
    outer_profiles = adsk.core.ObjectCollection.create()
    for profile in profiles:
        if is_outer_profile(profile):
            outer_profiles.add(profile)
    return outer_profiles

def perform_extrusion(sketch, distance, operation):
    app = adsk.core.Application.get()
    design = app.activeProduct
    root_comp = design.rootComponent

    # Get all profiles
    profiles = sketch.profiles
    if profiles.count == 0:
        raise RuntimeError("No profiles found in the sketch.")
    
    extrudes = root_comp.features.extrudeFeatures

    # Filter outer profiles
    outer_profiles = filter_outer_profiles(profiles)

    created_bodies = []

    for i in range(outer_profiles.count):
        profile = outer_profiles.item(i)
        
        # Create an extrusion input
        ext_input = extrudes.createInput(profile, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        
        # Define the extent of the extrusion (distance in mm)
        distance_value = adsk.core.ValueInput.createByReal(distance)
        ext_input.setDistanceExtent(False, distance_value)
        
        # Create the extrusion
        extrude = extrudes.add(ext_input)
        
        body = extrude.bodies.item(0)
        created_bodies.append(body)

    return created_bodies

def combine_occurrences(root_comp, created_bodies):
    app = adsk.core.Application.get()
    design = app.activeProduct
    root_comp = design.rootComponent

    combine_features = root_comp.features.combineFeatures

    # Iterate through created bodies and combine if they don't intersect
    for i in range(len(created_bodies) - 1):
        target_body = created_bodies[i]
        tool_body = created_bodies[i + 1]

        # Check for intersection
        combine_input = combine_features.createInput(target_body, adsk.core.ObjectCollection.create())
        combine_input.operation = adsk.fusion.FeatureOperations.IntersectFeatureOperation
        combine_input.setToolBodies(adsk.core.ObjectCollection.create().add(tool_body))

        combine_feature = combine_features.add(combine_input)
        
        if combine_feature.bodies.count == 0:
            # If no intersection, then combine
            combine_input = combine_features.createInput(target_body, adsk.core.ObjectCollection.create())
            combine_input.operation = adsk.fusion.FeatureOperations.JoinFeatureOperation
            combine_input.setToolBodies(adsk.core.ObjectCollection.create().add(tool_body))
            combine_features.add(combine_input)
        else:
            combine_feature.deleteMe()  # Remove intersect feature if intersection is found

def save_as_stl(output_path, filename):
    app = adsk.core.Application.get()
    design = app.activeProduct
    export_manager = design.exportManager
    stl_options = export_manager.createSTLExportOptions(design.rootComponent)
    stl_options.meshRefinement = adsk.fusion.MeshRefinementSettings.MeshRefinementHigh
    stl_options.filename = os.path.join(output_path, filename + '.stl')
    
    try:
        export_manager.execute(stl_options)
    except RuntimeError as e:
        raise RuntimeError(f"Failed to export STL: {e}")

def main():
    app = adsk.core.Application.get()
    ui = app.userInterface

    project_path = r"C:\Cuts"  # Use raw string to avoid escape issues
    output_path = r"C:\Cuts"  # Use raw string to avoid escape issues
    if not os.path.exists(output_path):
        os.makedirs(output_path)

    file_paths = [
        ("3mm.dxf", 0.3, 'join'),
        ("7mm.dxf", 0.7, 'join'),
        ("10mm.dxf", 1.0, 'join'),
        ("cut.dxf", 1.2, 'cut'),
        ("stamp.dxf", 0.8, 'join'),
        ("support.dxf", 0.3, 'join')
    ]

    design = app.activeProduct
    root_comp = design.rootComponent

    all_created_bodies = []

    for file_name, distance, operation in file_paths:
        file_path = os.path.join(project_path, file_name)
        try:
            sketch = import_dxf(file_path, root_comp)
            created_bodies = perform_extrusion(sketch, distance, operation)
            all_created_bodies.extend(created_bodies)
        except RuntimeError as e:
            ui.messageBox(f"Failed to import or process DXF file '{file_name}': {e}")
            continue
        except Exception as e:
            ui.messageBox(f"Unexpected error: {e}")
            continue

    try:
        combine_occurrences(root_comp, all_created_bodies)
        save_as_stl(output_path, os.path.basename(project_path))
        ui.messageBox('Successfully imported, processed, and saved the STL file.')
    except RuntimeError as e:
        ui.messageBox(f"Failed to save STL: {e}")

try:
    main()
except:
    app = adsk.core.Application.get()
    ui = app.userInterface
    ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

0 Likes

kandennti
Mentor
Mentor

Hi @grindcoretm -San.

 

It seemed like an interesting theme, so I gave it a try.
Run the script with “stamp.dxf” imported into the XY plane of the root component.

# Fusion360API Python script

import traceback
import adsk.core as core
import adsk.fusion as fusion

def run(context):
    ui: core.UserInterface = None
    try:
        app: core.Application = core.Application.get()
        ui = app.userInterface
        des: fusion.Design = app.activeProduct
        root: fusion.Component = des.rootComponent

        skt: fusion.Sketch = root.sketches.itemByName("stamp")

        profs = get_nested_profile_list(skt)
        if len(profs) < 1: return

        extFeats: fusion.ExtrudeFeatures = root.features.extrudeFeatures
        for prof in profs:
            extFeats.addSimple(
                prof,
                core.ValueInput.createByReal(0.05),
                fusion.FeatureOperations.NewBodyFeatureOperation,
            )

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def get_nested_profile_list(
        targetSketch: fusion.Sketch
) -> list[fusion.Profile]:
    
    checkBodies = []

    try:
        comp: fusion.Component = targetSketch.parentComponent

        extFeats: fusion.ExtrudeFeatures = comp.features.extrudeFeatures
        for prof in targetSketch.profiles:
            checkBodies.append(
                extFeats.addSimple(
                    prof,
                    core.ValueInput.createByReal(1.0),
                    fusion.FeatureOperations.NewBodyFeatureOperation,
                )
            )

        rayDirect: core.Vector3D = targetSketch.yDirection

        vec: core.Vector3D = rayDirect.copy()
        vec.normalize
        vec.scaleBy(0.001)

        profs = []

        for prof in targetSketch.profiles:
            p: core.Point3D = prof.face.pointOnFace

            hits = []
            while True:
                hitPoints: core.ObjectCollection = core.ObjectCollection.create()
                comp.findBRepUsingRay(
                    p,
                    rayDirect,
                    fusion.BRepEntityTypes.BRepFaceEntityType,
                    -1,
                    True,
                    hitPoints,
                )
                if hitPoints.count < 1: break

                p = hitPoints[0]
                hits.append(p)
                p.translateBy(vec)

            pointsDict = {}
            for p in hits:
                key = f"{round(p.x, 6)},{round(p.y, 6)},{round(p.z, 6)}"
                pointsDict.setdefault(key, 1)

            if len(pointsDict.keys()) % 2:
                profs.append(prof)

    except:
        print('Failed:\n{}'.format(traceback.format_exc()))

    finally:
        for body in checkBodies:
            body.deleteMe()

        return profs

The function get_nested_profile_list is a function to find the required profile.

 

The execution result looks like this.

1.png

0 Likes