Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Extruding multiple Profiles from One sketch

8 REPLIES 8
Reply
Message 1 of 9
Anonymous
3979 Views, 8 Replies

Extruding multiple Profiles from One sketch

How do you extrude a selection of multiple extrudes from one sketch using the Python Scripting?

 

For example: Extrudes.createInput(profile, operation) only takes one profile( which I understand to be any closed space in a specified sketch). How can you programattically extrude multiple profiles in one action from a Python Script. To see this action demonstrated just using the interface see the picture belowMultiProfileExtrude.png

 

How do I add this functionality to my Code?

8 REPLIES 8
Message 2 of 9
ekinsb
in reply to: Anonymous

You're correct that each closed area within a sketch is considered a "Profile".  In your example, there are three profiles in that sketch.  You can see this in the user interface as you move the mouse over the model and each of the areas highlights.

 

From the API you can query the sketch to get all of the profiles that Fusion has found.  To create an extrusion with more than one profile you can use an ObjectCollection that contains the profiles as input.  If you look at the Profile argument in the documentation it discusses the different types of input that can be used for that argument.  The example below illustrates this.

 

def multipleProfileExtrude():
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        des = adsk.fusion.Design.cast(app.activeProduct)     
        root = des.rootComponent
        
        # Create a new sketch on the X-Y base plane.
        sk = root.sketches.add(root.xYConstructionPlane)
        
        # Draw two overlapping circles.
        sk.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,-1,0), 2)
        sk.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,1,0), 2)
        
        ui.messageBox('The sketch contains ' + str(sk.profiles.count) + ' profiles.')
        
        # Create an object collection to use an input.
        profs = adsk.core.ObjectCollection.create()
        
        # Add all of the profiles to the collection.
        for prof in sk.profiles:
            profs.add(prof)
            
        # Create the extrusion.
        extrudeInput = root.features.extrudeFeatures.createInput(profs, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        extrudeInput.setDistanceExtent(False, adsk.core.ValueInput.createByReal(2))
        extrude = root.features.extrudeFeatures.add(extrudeInput)        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))    

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 3 of 9
Anonymous
in reply to: ekinsb

The problem I see with this approach is that you have to extrude all profiles. I'm trying to write code that extrudes only the profiles I create. Not all the closed profiles in the sketch.

Message 4 of 9
rudisoft
in reply to: Anonymous

I've got the same issue:

 

When creating some innercircles within an outer circle that don't overlap, I could give each inner circle one identifier (by name for example). Now, how do I itrate through all profiles, identify them by name and extrude them one by one?

Message 5 of 9
ekinsb
in reply to: rudisoft

If you have a complex sketch it can sometimes be difficult to find the specific profiles you need but I believe it should always be possible. A couple of points to remember.  First, you don't explicitly create profiles. You draw sketch entities and Fusion automatically determines the possible profiles.  Second, sketch entities can end up participating in many profiles.  In the example below I've drawn three overlapping circles.  This results in 7 profiles (each shown in a different color) and each circle participates in defining all 7 of the profiles.  This is probably one of the worst cases you could run into.profileExample.png

 

Another thing that can cause problems because it increases the complexity, is that when you create a new sketch using a face as input, the edges of the face are automatically included into the sketch it is also considered when the profiles are calculated. We'll be adding a new method soon to create a sketch on a face that will create the sketch without including the edges.  A couple of approaches you can use now is to delete all of the automatically created entities right after the sketch is created or change them all to construction so they won't participate in profile calculations.

 

Using the picture above as an example, and assuming you want to use the blue profile, you need to somehow figure out what makes the blue profile unique.  Assuming you created the three sketch circles in the same script so you should have references to those, you can use that information to help find the blue profile. What I see that makes the blue profile unique is that it's the only profile that is inside circle 1 and 2 and outside circle 3.  Below is my code that creates the three circles, finds the profile, and creates an extrusion.

 

import adsk.core, adsk.fusion, adsk.cam, traceback
_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)

def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface

        des = adsk.fusion.Design.cast(_app.activeProduct)
        root = des.rootComponent
        
        sk = root.sketches.add(root.xYConstructionPlane)
        circs = sk.sketchCurves.sketchCircles
        circ1 = circs.addByCenterRadius(adsk.core.Point3D.create(-5,-5,0), 7)        
        circ2 = circs.addByCenterRadius(adsk.core.Point3D.create(5,-5,0), 7)        
        circ3 = circs.addByCenterRadius(adsk.core.Point3D.create(0,4,0), 7)        
        
        prof = adsk.fusion.Profile.cast(None)
        for prof in sk.profiles:
            # Get the centroid of the current profile.
            profCenter = adsk.core.Point3D.cast(prof.areaProperties().centroid)
            
            # Check to see if the center is within circle 1.
            if profCenter.distanceTo(circ1.centerSketchPoint.geometry) < circ1.radius:
                # Check to see if the center is within circle 2.
                if profCenter.distanceTo(circ2.centerSketchPoint.geometry) < circ2.radius:
                    # Check to see if the center is outside circle 3.
                    if profCenter.distanceTo(circ3.centerSketchPoint.geometry) > circ3.radius:
                        break
                    
        # Create an extrusion with the found profile.
        root.features.extrudeFeatures.addSimple(prof, adsk.core.ValueInput.createByReal(5), adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
    except:
         _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

The problem with this code and somewhat the main point of my reply, is that this isn't likely to be useful to you or most anyone else.  The reason being that every set of sketch geometry is a little different and the approach you might take to figure out which profile(s) you want to use will be different in each case.

 

Another thing to be aware of is what's available with a profile.  In the example above I take advantage of the fact that you can get area properties from a profile but you can also get the sketch curves that are used to define the profile.  That's actually more useful in most cases but in my example above since every circle participates in every profile it's not useful.  A profile is made up of one or more loops.  If it has more than one loop then there is one outer loop and one or more inner loops.  For example, in the sketch pictured below there are two profiles, the one highlighted in blue and the one in the triangle. The blue one is made up of two loops; the outer rectangle and the inner triangle. There could also be additional inner loops but a profile always has only one outer loop. If I want the blue profile I can check to see which of the two profiles has two loops. In other cases it can be useful to check which which sketch entities are used to define a profile. Each loop provides the profile curves that make up that loop and each profile curve can tell you which sketch entity it's based on. One way to think of getting profiles is that it's like solving a puzzle. You're given a certain set of tools and you need to figure out how to use those tools to get to the specific solution you want.ProfileExample2.png

 

 

 

 

 

 

 

 

 

 

 


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 6 of 9
rudisoft
in reply to: ekinsb

Dear Brian,

 

thanks for your quick answer. Really appreceate your API, even though I'm just a hobbyist and just starting to use it. The solution to my problem turned out to be a simple one since my problem is simpler than in your analysis above:

 

Make a separate sketch of the smaller circles and extrude. This way, I don't need to either guess or make more geometrical considerations. 

Message 7 of 9
rudisoft
in reply to: ekinsb

Hi guys,

 

so, if I have a sketch that looks like this

one.PNG

 

and want to have this by extruding all but the largest shape:

two.PNG

 

I have created the following code

Ptr<ObjectCollection> pinsExtrudeProfiles = ObjectCollection::create();
for (int j = 0; j < z2; j++) {
Ptr<Point3D> point = Point3D::create(r2*cos(2 * PI*j / z2), r2*sin(2 * PI*j / z2), 0);
Ptr<SketchCircle>circle = pHolderSketchCircles->addByCenterRadius(point, dc / 2);
}

// creating the outer rim Ptr<SketchCircle>cirle2 = pHolderSketchCircles->addByCenterRadius(Point3D::create(0, 0, 0), r2 + dc / 2); Ptr<SketchCircle>cirle3 = pHolderSketchCircles->addByCenterRadius(Point3D::create(0, 0, 0), r2 ); Ptr<Profiles> profiles = pHolderSketch->profiles(); /* There are four different types of profiles in this sketch now: The largest one is the center, star shaped The second largest is the thing between the pins The third largest is the outer part of the pin that was intersected by the second circle The fourth largest is the inner part of the pin that was intersected by the 2nd circle */ int areas[4] = {0,0,0,0}; for (int j = 0; j < profiles->count()-1; j++) { Ptr<Profile> profile = profiles->item(j); // rounding is important since the profile areas are pretty much all different // however, there are four clusters that we need to identify. int area = (int)(profile->areaProperties()->area() * 100000) ; bool skipped = false; for (int k = 0; k < 4; k++) { if (areas[k] == area) { skipped = true; break; // skip } } if (!skipped) { for (int k = 0; k < 4; k++) { if (areas[k] == 0) { areas[k] = area; break; } } } } // We need the first, second and third largest profile. Therefore we sort. std::sort(areas, areas + 4); for (int j = 0; j < profiles->count(); j++) { Ptr<Profile> profile = profiles->item(j); int area = (int)(profile->areaProperties()->area() * 100000); if (area == areas[0] || area == areas[1] || area == areas[2]) { pinsExtrudeProfiles->add(profile); } } Ptr<ExtrudeFeatureInput> pinsextrudeFeature = pinsextrudes->createInput(pinsExtrudeProfiles,
FeatureOperations::JoinFeatureOperation); pinsextrudeFeature->setDistanceExtent(false, ValueInput::createByReal(camthickness)); Ptr<ExtrudeFeature> pinsext = pinsextrudes->add(pinsextrudeFeature); adsk::doEvents();

Is this the best way of doing it? I have some multiple issues with this:

- the areas turn out to be not of equal size numerically, therefore I need to round them. 

- first, finding out which different shape sizes are there, then sorting them before selecting everything else but the largest one seems awkward.

- calculation takes up quite some time. Is there a way to programmatically turn of history

 

 Is it too much to ask for a shape selection query language? I would certainly appreceate some sort of

Ptr<ObjectCollection> pinsExtrudeProfiles ="select 
top(profiles->count()-1)
from pHolderSketch->profiles()
order by profile->areaProperties()->area() desc";

Thanks in advance,

 

rudisoft

 

Message 8 of 9
ekinsb
in reply to: rudisoft

How about this?  Instead of looking at the shape, look at the topology of each profile.  All of the profiles, except for the big center one, are made up of 5 or less segments.  I did a quick test in Python and here's the code.

 

 

# Add all profiles that have 5 or less segments.
extProfiles = adsk.core.ObjectCollection.create()
prof = adsk.fusion.Profile.cast(None)
for prof in sk.profiles:
    # Get the single loop of the profile.
loop = prof.profileLoops.item(0) if loop.profileCurves.count <= 5: extProfiles.add(prof) rootComp.features.extrudeFeatures.addSimple(extProfiles, adsk.core.ValueInput.createByReal(dc), adsk.fusion.FeatureOperations.NewBodyFeatureOperation)

 


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 9 of 9
rudisoft
in reply to: ekinsb

Thanks Brian,

 

I translated this to C++ and it works like a charm. So here it is for anybody who wants to grab.

Ptr<SketchCircle>cirle2 = pHolderSketchCircles->addByCenterRadius(Point3D::create(0, 0, 0), r2 + dc / 2);
Ptr<SketchCircle>cirle3 = pHolderSketchCircles->addByCenterRadius(Point3D::create(0, 0, 0), r2);
Ptr<Profiles> profiles = pHolderSketch->profiles();
			
for (int k = 0; k < profiles->count(); k++) {
	Ptr<Profile> profile = profiles->item(k);
	Ptr<ProfileLoop> loop = profile->profileLoops()->item(0);
	if(loop->profileCurves()->count()<=5){
		pinsExtrudeProfiles->add(profile);
	}
}
	
Ptr<ExtrudeFeatureInput> pinsextrudeFeature = pinsextrudes->createInput(pinsExtrudeProfiles, FeatureOperations::JoinFeatureOperation);
pinsextrudeFeature->setDistanceExtent(false, ValueInput::createByReal(camthickness));
Ptr<ExtrudeFeature> pinsext = pinsextrudes->add(pinsextrudeFeature);
Ptr<BRepBody>pinsBody = pinsext->bodies()->item(0);

I'll certainly will look into profile loops a little closer in the future.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report