Flange Feature Sample

Description

Demonstrates accessing and creating sheet metal flange features including base flange, contour flange, and edge flange.

To run the sample script, have a design open in Fusion's DESIGN workspace that contains a sheet metal body in the root component. The body must have at least one linear edge on its outside that is valid for a flange. A design created with the Sheet Metal > Create > Flange commands, or any design containing a base flange, satisfies this.

The script first iterates over any flange features that already exist in the design and reads the settings from each definition, so the reading portion reports nothing if the design has no flanges yet. It then finds the first linear edge on the first body in the root component and uses it to create a new edge flange feature. Reading the edges back from the created feature requires rolling the timeline marker to immediately before the feature, which the script does using TimelineObject.rollTo.

Code Samples

import adsk.core, adsk.fusion, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
       
        # Get active design        
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
         
        # Get the root component
        rootComp = design.rootComponent

        # Get features
        features = rootComp.features
        flangeFeatures = features.flangeFeatures

        # Get existing flange features count
        initialCount = flangeFeatures.count
        
        # Test iteration and access
        for i in range(flangeFeatures.count):
            flange = flangeFeatures.item(i)
            defType = flange.definitionType
            definition = flange.definition
            
            # Access definition based on type
            if defType == adsk.fusion.FlangeFeatureDefinitionTypes.BaseFlangeFeatureDefinitionType:
                baseDef = adsk.fusion.BaseFlangeFeatureDefinition.cast(definition)
                orientation = baseDef.orientation
                profiles = baseDef.profiles
                
            elif defType == adsk.fusion.FlangeFeatureDefinitionTypes.ContourFlangeFeatureDefinitionType:
                contourDef = adsk.fusion.ContourFlangeFeatureDefinition.cast(definition)
                orientation = contourDef.orientation
                dirType = contourDef.direction
                distance = contourDef.distance
                profiles = contourDef.profiles

            elif defType == adsk.fusion.FlangeFeatureDefinitionTypes.EdgeFlangeFeatureDefinitionType:
                edgeDef = adsk.fusion.EdgeFlangeFeatureDefinition.cast(definition)
                heightDatum = edgeDef.heightDatumType
                bendPos = edgeDef.bendPositionType
                isMitered = edgeDef.isMiteredCorners
                isFlipped = edgeDef.isFlipped
                extentType = edgeDef.extentType
                angle = edgeDef.angle
                # Edge path resolution requires rolling back before reading feature edges.
                tlObj = flange.timelineObject
                if tlObj and tlObj.rollTo(True):
                    edges = edgeDef.edgeDefinitions
        
        # Test itemByName
        if flangeFeatures.count > 0:
            firstFlange = flangeFeatures.item(0)
            name = firstFlange.name
            foundFlange = flangeFeatures.itemByName(name)
            
        # Get geometry from body to create edge flange
        brepBodies = rootComp.bRepBodies
        body = brepBodies.item(0)
        edges = body.edges
        
        # Two adjacent edges on the base face (APISampleSheetMetalFlange.f3d: indices 8, 11).
        linearEdges = [edges.item(8), edges.item(11)]

        # Create edge flange input
        distance = adsk.core.ValueInput.createByReal(2.0)
        edgeFlangeInput = flangeFeatures.createEdgeFlangeInput(linearEdges, distance)

        # Configure edge flange input properties
        edgeFlangeInput.heightDatumType = adsk.fusion.FlangeHeightDatumTypes.OuterFacesFlangeHeightDatumType
        edgeFlangeInput.bendPositionType = adsk.fusion.BendPositionTypes.StartEdgeBendPositionType
        edgeFlangeInput.isMiteredCorners = True
        edgeFlangeInput.isFlipped = False

        # Set angle
        angle = adsk.core.ValueInput.createByReal(1.5708)  # 90 degrees in radians
        edgeFlangeInput.angle = angle

        # Demonstrate sheet metal rule overrides on the input
        # Override the bend radius
        inputBendRadiusOverride = edgeFlangeInput.bendRadiusOverride
        if inputBendRadiusOverride:
            radiusValue = adsk.core.ValueInput.createByString('0.15 cm')
            inputBendRadiusOverride.setOverride(radiusValue)

        # Override the bend relief
        inputBendReliefOverride = edgeFlangeInput.bendReliefOverride
        if inputBendReliefOverride:
            reliefWidth = adsk.core.ValueInput.createByString('0.1 cm')
            reliefDepth = adsk.core.ValueInput.createByString('0.1 cm')
            reliefRemnant = adsk.core.ValueInput.createByString('0.05 cm')
            inputBendReliefOverride.setOverride(
                adsk.fusion.BendReliefShapes.RoundBendReliefShape,
                reliefWidth, reliefDepth, reliefRemnant)

        # Override the two-bend corner relief
        inputTwoBendOverride = edgeFlangeInput.twoBendCornerOverride
        if inputTwoBendOverride:
            cornerSize = adsk.core.ValueInput.createByString('0.1 cm')
            inputTwoBendOverride.setOverride(
                adsk.fusion.TwoBendReliefShapes.RoundTwoBendReliefShape, cornerSize,
                adsk.fusion.TwoBendCornerOverridePlacements.TangentTwoBendCornerOverridePlacement)

        # Get edge definitions
        edgeDefs = edgeFlangeInput.edgeDefinitions
        
        # Create the edge flange feature
        edgeFlange = flangeFeatures.add(edgeFlangeInput)

        # Release stale BRepEdge references — topology is rebuilt after add()
        linearEdges = []
        edges = None
        edgeFlangeInput = None

        # Verify the feature was created
        if edgeFlange:
            assert flangeFeatures.count == initialCount + 1, f"Expected {initialCount + 1} flanges, got {flangeFeatures.count}"

            # Edge path resolution requires rolling back before reading feature edges.
            edgeFlangeDef = adsk.fusion.EdgeFlangeFeatureDefinition.cast(edgeFlange.definition)
            edgeFlangeTl = edgeFlange.timelineObject
            if edgeFlangeDef and edgeFlangeTl and edgeFlangeTl.rollTo(True):
                featureEdgeDefs = edgeFlangeDef.edgeDefinitions
                assert featureEdgeDefs and featureEdgeDefs.count > 0
           
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
            pass
#include <Core/Application/Application.h>
#include <Core/Application/Document.h>
#include <Core/Application/ValueInput.h>
#include <Core/UserInterface/UserInterface.h>

#include <Fusion/Components/Component.h>
#include <Fusion/BRep/BRepBodies.h>
#include <Fusion/BRep/BRepBody.h>
#include <Fusion/BRep/BRepEdge.h>
#include <Fusion/BRep/BRepEdges.h>
#include <Fusion/Features/Features.h>
#include <Fusion/SheetMetal/FlangeFeature.h>
#include <Fusion/SheetMetal/FlangeFeatures.h>
#include <Fusion/SheetMetal/FlangeFeatureDefinition.h>
#include <Fusion/SheetMetal/BaseFlangeFeatureDefinition.h>
#include <Fusion/SheetMetal/ContourFlangeFeatureDefinition.h>
#include <Fusion/SheetMetal/EdgeFlangeFeatureDefinition.h>
#include <Fusion/SheetMetal/EdgeFlangeInput.h>
#include <Fusion/SheetMetal/FlangeEdgeDefinitions.h>
#include <Fusion/SheetMetal/FlangeEdgeDefinition.h>
#include <Fusion/SheetMetal/BendRadiusOverride.h>
#include <Fusion/Fusion/Design.h>
#include <Fusion/Fusion/ModelParameter.h>
#include <Fusion/Fusion/TimelineObject.h>

using namespace adsk::core;
using namespace adsk::fusion;

Ptr<UserInterface> ui;

extern "C" XI_EXPORT bool run(const char* context)
{
    Ptr<Application> app = Application::get();
    if (!app)
        return false;

    ui = app->userInterface();
    if (!ui)
        return false;


    // Get active design
    Ptr<Product> product = app->activeProduct();
    if (!product)
        return false;

    Ptr<Design> design = product;
    if (!design)
        return false;

    // Get root component in this design
    Ptr<Component> rootComp = design->rootComponent();
    if (!rootComp)
        return false;

    // Get flange features
    Ptr<Features> features = rootComp->features();
    if (!features)
        return false;

    Ptr<FlangeFeatures> flangeFeatures = features->flangeFeatures();
    if (!flangeFeatures)
        return false;

    // Test collection access
    size_t count = flangeFeatures->count();

    // Test iteration and definition access
    for (size_t i = 0; i < count; ++i)
    {
        Ptr<FlangeFeature> flange = flangeFeatures->item(i);

        FlangeFeatureDefinitionTypes defType = flange->definitionType();

        Ptr<FlangeFeatureDefinition> definition = flange->definition();

        if (defType == FlangeFeatureDefinitionTypes::BaseFlangeFeatureDefinitionType)
        {
            Ptr<BaseFlangeFeatureDefinition> baseDef = definition;
            FlangeOrientations orientation = baseDef->orientation();
        }
        else if (defType == FlangeFeatureDefinitionTypes::ContourFlangeFeatureDefinitionType)
        {
            Ptr<ContourFlangeFeatureDefinition> contourDef = definition;
            FlangeOrientations orientation = contourDef->orientation();
            FlangeDirections dirType = contourDef->direction();
            Ptr<ModelParameter> distance = contourDef->distance();
        }
        else if (defType == FlangeFeatureDefinitionTypes::EdgeFlangeFeatureDefinitionType)
        {
            Ptr<EdgeFlangeFeatureDefinition> edgeDef = definition;
            FlangeHeightDatumTypes heightDatum = edgeDef->heightDatumType();
            BendPositionTypes bendPos = edgeDef->bendPositionType();
            (void)edgeDef->isMiteredCorners();
            (void)edgeDef->isFlipped();
            Ptr<ModelParameter> angle = edgeDef->angle();
        }
    }

    // Test itemByName
    Ptr<FlangeFeature> firstFlange = flangeFeatures->item(0);
    std::string name = firstFlange->name();
    Ptr<FlangeFeature> foundFlange = flangeFeatures->itemByName(name.c_str());

    // Get body for creating edge flange
    Ptr<BRepBodies> bodies = rootComp->bRepBodies();

    Ptr<BRepBody> body = bodies->item(0);

    Ptr<BRepEdges> edges = body->edges();

    // Two adjacent edges on the base face (APISampleSheetMetalFlange.f3d: indices 8, 11).
    std::vector<Ptr<BRepEdge>> linearEdges = {edges->item(8), edges->item(11)};

    // Create edge flange input
    Ptr<ValueInput> distance = ValueInput::createByReal(2.0);

    Ptr<EdgeFlangeInput> edgeFlangeInput = flangeFeatures->createEdgeFlangeInput(linearEdges, distance);

    // Configure input properties
    edgeFlangeInput->heightDatumType(FlangeHeightDatumTypes::OuterFacesFlangeHeightDatumType);
    edgeFlangeInput->bendPositionType(BendPositionTypes::StartEdgeBendPositionType);
    edgeFlangeInput->isMiteredCorners(true);
    edgeFlangeInput->isFlipped(false);

    // Set angle
    Ptr<ValueInput> angle = ValueInput::createByReal(1.5708); // 90 degrees
    edgeFlangeInput->angle(angle);

    // Demonstrate sheet metal rule overrides on the input
    // Override the bend radius
    auto inputBendRadiusOverride = edgeFlangeInput->bendRadiusOverride();
    Ptr<ValueInput> radiusValue = ValueInput::createByString("0.15 cm");

    // Override the bend relief
    auto inputBendReliefOverride = edgeFlangeInput->bendReliefOverride();
    Ptr<ValueInput> reliefWidth = ValueInput::createByString("0.1 cm");
    Ptr<ValueInput> reliefDepth = ValueInput::createByString("0.1 cm");
    Ptr<ValueInput> reliefRemnant = ValueInput::createByString("0.05 cm");
        BendReliefShapes::RoundBendReliefShape, reliefWidth, reliefDepth, reliefRemnant));

    // Override the two-bend corner relief
    auto inputTwoBendOverride = edgeFlangeInput->twoBendCornerOverride();
    Ptr<ValueInput> cornerSize = ValueInput::createByString("0.1 cm");
        TwoBendReliefShapes::RoundTwoBendReliefShape,
        cornerSize,
        TwoBendCornerOverridePlacements::TangentTwoBendCornerOverridePlacement));

    // Get edge definitions
    Ptr<FlangeEdgeDefinitions> edgeDefs = edgeFlangeInput->edgeDefinitions();

    // Create the edge flange
    Ptr<FlangeFeature> edgeFlange = flangeFeatures->add(edgeFlangeInput);

    // Verify the feature was created

    // Edge path resolution requires rolling back to before the flange's topology rebuild.
    Ptr<FlangeFeatureDefinition> edgeFlangeDef = edgeFlange->definition();
    Ptr<EdgeFlangeFeatureDefinition> edgeFlangeFeatureDef = edgeFlangeDef;
    Ptr<TimelineObject> edgeFlangeTimeline = edgeFlange->timelineObject();
    Ptr<FlangeEdgeDefinitions> featureEdgeDefs = edgeFlangeFeatureDef->edgeDefinitions();


    return true;
}