Is there a less expensive (faster) way to draw lines in a sketch?

Is there a less expensive (faster) way to draw lines in a sketch?

owendelong
Contributor Contributor
1,827 Views
17 Replies
Message 1 of 18

Is there a less expensive (faster) way to draw lines in a sketch?

owendelong
Contributor
Contributor

Currently, I'm using this:

 

 

tickLine = sketchLines.addByTwoPoints(adsk.core.Point3D.create(Top, xpos, 0), adsk.core.Point3D.create(Bottom, xpos, 0))

 

to draw a series of lines in a sketch.
On average, this call seems to take approximately 200ms to complete, which isn't that long if you're only drawing a few lines, but in this case, I'm generating a several hundred lines, so it leads to a significant wait for the end user overall.
 
I don't need 3d lines (as you can see, Z is fixed at 0 in both coordinates). If there's an alternative mechanism (whether another method in the sketchLines class or otherwise that is faster, I think that's very desirable in this instance.
 
Thanks in advance for any pointers.
 
0 Likes
Accepted solutions (2)
1,828 Views
17 Replies
Replies (17)
Message 2 of 18

kandennti
Mentor
Mentor
Accepted solution

Hi @owendelong -San.

 

Sketch processing is slow.
The only thing that might work is the Sketch.isComputeDeferred property, but it will still be slow if there is a lot of it.

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-a174973f-79ac-4330-8dd7-3d3ded63e63e 

 

Other options are,
・Create your own logic to create the DXF and load the DXF.
・Abandon the sketch and create the 3D model directly.

0 Likes
Message 3 of 18

owendelong
Contributor
Contributor

Since the point here is to produce a DXF that can be used for Laser Cutting, direct 3D object creation isn't really a useful solution.

 

I suppose creating the DXF without involving Fusion is an option, but that seems like it would involve a significant amount of recoding. I guess for now, I'll just live with the slow.

 

Interestingly, it seems to get slower the more lines you have in the sketch.

 

I will look into the deferred Compute option.

 

0 Likes
Message 4 of 18

owendelong
Contributor
Contributor

Deferred Compute isn't a panacea, as you stated, but it definitely helped quite a bit. Script now seems to build the sketch in about half the previous time.

 

Message 5 of 18

owendelong
Contributor
Contributor
FWIW, I gained a LOT more speed by switching from storing the variables in a python dictionary to storing them as Fusion User Parameters and significantly reducing progress reporting. Not sure how much each of these contributed, but since line drawing itself accelerated greatly (single API call time in/time out difference greatly reduced) I have to assume a significant amount came from the change to User Parameters.

I find this surprising, but YMMV and I figured I'd share it here.
Message 6 of 18

kandennti
Mentor
Mentor

@owendelong -San.

 

Very interesting. Could you be more specific? Many people must have the same problem.

0 Likes
Message 7 of 18

owendelong
Contributor
Contributor

Well.. I'm not sure how much more specific I can be, but basically, I turned this (times 7 python dictionary entries):

myParameters = { 'Type' : False }

 

into this:

if (myParameters.itemByName("Type"))
  myParameters.itemByName("Type").value = False
else:
  myParameters.add("Type",adsk.core.ValueInput.createByBoolean(False),"",
                   "False for Linear, True for Grid")

 

I also removed several calls to this function:

def debug(ui, *args, **kwargs):
    buf = io.StringIO()
    print(*args, **kwargs, file=buf)
    ui.palettes.itemById('TextCommands').writeText(buf.getvalue())

 

However, where most of the performance improvement happened, wasn't where most of the removed calls were located, so I have to think that the former had more to do with the speed gain than the latter.

 

Unfortunately, it's a fairly hairy script (with some embarrassingly quick and dirty code elements) that I think would have limited value to the community.

Message 8 of 18

OceanHydroAU
Collaborator
Collaborator
Accepted solution

This sounds promising:-

sketch.isComputeDeferred = True / sketch.isComputeDeferred = False

but does not work for me.

 

But the reason it is slow is because every new line you're drawing "touches" in some way some other thing already, and those 200ms is Fusion working it's hardest to prevent inserting duplicated things.  If you can add lines in an order to minimize how they coincide with anything else, that will drastically speed things up.

 

I was able to improve some really bad issues by inserting things in a deliberately wrong place, then moving them to where they should be.

 

A better bet would be to investigate how to turn off that optimising thing that's de-duping your inserts.

 

 

Message 9 of 18

OceanHydroAU
Collaborator
Collaborator

you know that python can directly create DXF files (ezdxf I think?), and that fusion360 can read them - right ?

0 Likes
Message 10 of 18

kandennti
Mentor
Mentor

@owendelong -San.

 

I didn't understand it even though you went out of your way to explain it to me. I am sorry.

 

I know this is a different topic, but can you create a user parameter without units here? I get an error.

1.png

0 Likes
Message 11 of 18

owendelong
Contributor
Contributor
Are you sure that the error you are getting is from the "" and not from the type of value you are passing?

Note that there is a difference between:
parameterobject.add("name",value,"","description")
and:
parameterobject.add("name",adsk.core.ValueInput.createByBoolean(value),"","description")

Namely that the second argument (which is usually reported in the error as argument 3 to a deeper function because that deeper function is called with a prepend of '''self,''' to the argument list (gotta love objects).


The former will cause a type error because the value you are passing is merely a value and not a valueInput object (which is the type required by the function).

I struggled with that one for quite a while myself.
0 Likes
Message 12 of 18

owendelong
Contributor
Contributor
Yes, but this exercise is as much about learning the Fusion API as it was about generating DXF files to laser cut rulers. I keep hoping that some day, someone will build a CAM interface with post processor for LightBurn or other Laser cutters, but so far, I have to manually post-process DXF files.
0 Likes
Message 13 of 18

owendelong
Contributor
Contributor

That actually makes some sense as to why making it into userParameters instead of an internal python Dictionary in my script would accelerate things, then. Since the values are being pulled from Fusion's userParameters, it has probably cached/pre-computed a number of things related to de-dup.

 

0 Likes
Message 14 of 18

kandennti
Mentor
Mentor

@owendelong -San.

 

Thanks for explaining the parameters. I was indeed able to create a unitless user parameter with the CreateByReal method.

Can I create parameters with Boolean type?

1.png


I have tested with the following code, but they all give an error.

# adsk.fusion360API Python script

import traceback
import adsk.core
import adsk.fusion

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

        myParameters: adsk.fusion.UserParameters = des.userParameters

        myParameters.add(
            "Test",
            adsk.core.ValueInput.createByBoolean(False),
            "",
            ""
        )

        myParameters.add(
            "Test",
            False,
            "",
            ""
        )

        myParameters.add(
            "Test",
            adsk.core.ValueInput.createByString("False"),
            "",
            ""
        )

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


The CreateByString method does not generate an error, but it does on the GUI.

0 Likes
Message 15 of 18

owendelong
Contributor
Contributor

I could have sworn I had createByBoolean working previously, but I certainly haven't been able to get it working since it stopped. Because the script is under very active development, there were a lot of changes at the same time, so it's possible that the switch from createByReal to createByBoolean happened after the last test run and before the other changes that prompted the next test run where things were broken.

 

Interestingly, as I also mentioned in the other thread, assignment of a boolean value to an existing parameter seems to work (e.g. userParameter_var.value=True), so I'll probably create a Real and then set the boolean value as a workaround for now.

 

Message 16 of 18

OceanHydroAU
Collaborator
Collaborator
I'm almost finished an add-in which comes very close to what you're talking about. Sounds almost trivial to re-purpose it to output stuff for cutters. Your phrase "laser cut rulers." puzzles me slightly (I'm guessing these are long rectangular things with units etched on them?). What exactly would your dream "CAM interface" be doing for you here (my guess: generating a DXF file with cut lines and etch markings, right? Anything else?)
0 Likes
Message 17 of 18

owendelong
Contributor
Contributor

Etch/Cut DXF layers would be good. Native LightBurn support or similar would be even better, one where I could identify the different power/speed/pulse(where applicable) settings as part of the CAM process (similar to the way you select different end mills for a milling process) and output a file that can be directly loaded into the LASER control software would be unimaginably wonderful.

 

(LASER equivalent of the ShopBot post processor, for example)

 

Yes, the current project is transparent acrylic rulers. The script I'm writing is capable of producing sketches suitable for cutting thin wood or acrylic on the laser with etched unit lines. It can do either linear (one or two long sides with same or different units (imperial/metric)) or grid (frequently used in graphic layout and/or textiles) rulers with the same units on all 4 sides, frequently wider (think 7-15cm wide and upwards of 40cm long) and unit grids with sub-unit ticks on all the grid lines.

 

0 Likes
Message 18 of 18

BrianEkins
Mentor
Mentor

You can set two things on a sketch that should speed up the creation.

  1. Sketch.isComputeDeferred - This has already been mentioned and disables the standard solving done as you draw sketch geometry.
  2. Sketch.areProfilesShown - This is also available in the UI and stops the display of profiles in the sketch. It also stops the computation of profiles, which will be the most beneficial when creating sketch geometry with the API.

Any operation in Fusion has a few costs. First is the internal cost of calculating the result for whatever you're creating. This is trivial for a sketch line but expensive for a complex loft. Second, the result may also involve other calculations to update related geometry. When drawing sketch geometry, this includes the things we're trying to skip with the properties listed above. When editing a feature or changing a parameter, there is the cost of updating all of the features in the timeline after the feature that is modified. Finally, there is some cost of transacting all of that work so it can be undone.  

 

Regarding the Boolean parameter, Fusion only supports numeric parameters and as a result, that's all the API supports.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com