Announcements
Autodesk Community will be read-only between April 26 and April 27 as we complete essential maintenance. We will remove this banner once completed. Thanks for your understanding

Bug Report? deleteMe Method Not Deleting All Sketch Curves

therealsamchaney
Advocate

Bug Report? deleteMe Method Not Deleting All Sketch Curves

therealsamchaney
Advocate
Advocate

I wrote a little script to find all projected sketch curves and delete them all. The script accurately counts that there are 10 projected sketch curves, then I call deleteMe method on all of them (in a for loop) but several remain untouched. It seems to be exactly every other curve that remains untouched. 

It seems strange that they are not all deleted. I've even tried deleting all curves in the sketch but it still only deletes half of the sketches.

Why is the deleteMe method only deleting half of the curves and skipping the others? Is there some trick to iterating over the sketchCurve objects in the collection? Is this a bug?

Here is a link to the screencast. I've attached the test design file here. The code is below:

 

#Author-Sam Chaney
#Description-Selects and deletes all projected sketch entities

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

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        design = adsk.fusion.Design.cast(app.activeProduct)
        active_component = design.activeComponent
        sketches = active_component.sketches
        active_sketch = adsk.core.Application.get().activeEditObject #Use this instead of chosen_sketch if you want to use active sketch
        
        sketch_name, cancelled  = ui.inputBox('Enter exact name of sketch to delete projected entities')
        if cancelled:
            ui.messageBox('Cancelled!')
            sys.exit('Cancelled')
        if sketches.itemByName(sketch_name) is None:
            ui.messageBox(f'Sketch named "{sketch_name}" not found')
            sys.exit('Sketch not found')

        chosen_sketch = sketches.itemByName(sketch_name)
        
        curves = chosen_sketch.sketchCurves
        ui.messageBox(f'Curve count is {curves.count}')
        lines = curves.sketchLines
        points = chosen_sketch.sketchPoints

        def is_projected(entity):
            projected_entities =[]
            if entity.isLinked:
                projected_entities.append(entity)
            return projected_entities

        def delete_projected(collection):
            for entity in collection:
                # if entity.isLinked:
                    # ui.messageBox('entity was linked')
                entity.deleteMe()
                
        def delete_all(collection):
            for entity in collection:
                entity.deleteMe # should delete all curves in sketch no matter what
                    
        delete_projected(curves)
        delete_all(curves) # even this only deletes 5 lines. It's every other line

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

 

 

0 Likes
Reply
Accepted solutions (2)
392 Views
6 Replies
Replies (6)

JeromeBriot
Mentor
Mentor
Accepted solution

Hello,

 

Actually, this is not a bug. You have to delete the objects in reverse order:

 

#Author-Sam Chaney
#Description-Selects and deletes all projected sketch entities

from audioop import reverse
import adsk.core, adsk.fusion, adsk.cam, traceback, sys

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        design = adsk.fusion.Design.cast(app.activeProduct)
        active_component = design.activeComponent
        sketches = active_component.sketches
        active_sketch = adsk.core.Application.get().activeEditObject #Use this instead of chosen_sketch if you want to use active sketch

        sketch_name, cancelled  = ui.inputBox('Enter exact name of sketch to delete projected entities')
        if cancelled:
            ui.messageBox('Cancelled!')
            sys.exit('Cancelled')
        if sketches.itemByName(sketch_name) is None:
            ui.messageBox(f'Sketch named "{sketch_name}" not found')
            sys.exit('Sketch not found')

        chosen_sketch = sketches.itemByName(sketch_name)

        curves = chosen_sketch.sketchCurves
        ui.messageBox(f'Curve count is {curves.count}')
        lines = curves.sketchLines
        points = chosen_sketch.sketchPoints

        def is_projected(entity):
            projected_entities =[]
            if entity.isLinked:
                projected_entities.append(entity)
            return projected_entities

        def delete_projected(collection):
            for entity in reversed(collection):
                entity.deleteMe()

        def delete_all(collection):
            for entity in reversed(collection):
                entity.deleteMe()

        delete_projected(curves)
        delete_all(curves) # even this only deletes 5 lines. It's every other line

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

 

2 Likes

j.han97
Advocate
Advocate
Accepted solution

Hi @therealsamchaney

 

I guess what really happened is that the list (or collection) has been changed when you delete its items. See example below for explanation:

a = [1, 2, 3, 4, 5, 6]
for a1 in a:
    a.remove(a1)

print(a)

 

 

You will get 

 

[2, 4, 6]

 

 

However, if you loop over a copy of the list (or collection):

 

b = [1, 2, 3, 4, 5, 6]
for b1 in list(b):
    b.remove(b1)

print(b)

 

You will get the expected result:

 

[]

 

 

I would suggest you to try modifying the lines:

 

for entity in collection:

 

to

 

for entity in list(collection):

 

 

Hope this helps.

1 Like

therealsamchaney
Advocate
Advocate

@JeromeBriot thank you very much. Can you give more information about the SketchCurves collection object? Does it work just like a simple python list? If so then it would make sense as it would be just like this issue with python lists which causes undefined behavior.

Initially I guessed that the deleteMe method just removed them from the sketch and not the collection but it makes sense that Fusion would update its state between each iteration and thus update the sketch collection object, so then the index is moved over one.

0 Likes

therealsamchaney
Advocate
Advocate

Thank you. This makes sense. After using deleteMe on the first curve, I guess that Fusion must update its state making the new curves collection 1 item smaller. Now the first index is on curve 2 but I'm telling it to go to the next index so it skips curve 2 and ends up on curve 3. Repeat and you're left with every other curve. 

0 Likes

JeromeBriot
Mentor
Mentor

@therealsamchaney  a écrit :

Can you give more information about the SketchCurves collection object?


Read the documentation: Python Specific Issues - Working with Collections

 


@therealsamchaney  a écrit :

After using deleteMe on the first curve, I guess that Fusion must update its state making the new curves collection 1 item smaller. Now the first index is on curve 2 but I'm telling it to go to the next index so it skips curve 2 and ends up on curve 3. Repeat and you're left with every other curve. 


That's exactly what @j.han97 explained in his message previously.

 

0 Likes

therealsamchaney
Advocate
Advocate

I just wanted to say that normally in python when iterating over a list and modifying it, you make a copy of it and most people I see tend to use slice notation like 

for item in my_list[:]:
    #do something

however, the Fusion 360 sketchCurves collection object is not a python list, so you cannot use that notation. I think @j.han97 's answer is the best approach because it makes the collection into a normal Python list of sketchCurve objects and doesn't touch the actual collection object directly.

0 Likes