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: 

Exporting area of selected faces from a body

5 REPLIES 5
Reply
Message 1 of 6
j4n.vokurka
209 Views, 5 Replies

Exporting area of selected faces from a body

Hey,

I need to export the total area of faces I select from a body to .csv/.txt. I should also be able to change the color of selected faces to highlight them. I've spent some time reading through forums and watching tutorials. Although I mostly found out which objects to use for this task, I'm new to API and have problems scripting it to work properly.  I've managed to put together only few parts of the code, not any solid basis on which to build. I would be greatful if anybody would sent me something that would help me.

I use this logic:

Select face(s) from random body - add them and the area value to an array - let the user select color for the array - calculate the total area of these faces - export it

Things I tried to use:

BRepBodies, BRepFaces - Appearance, ColorProperty -  UserInterface.activeSelectionChanged Event - UserParameters.add Method - areaProperties

Thanks in advance for any help 

 

 

 

5 REPLIES 5
Message 2 of 6
kandennti
in reply to: j4n.vokurka

Hi @j4n.vokurka .

 

I did not understand what you meant about array and color.

 

The following sample displays the area of several selected surfaces and exports them to a file.

 

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core

_app: adsk.core.Application = None
_ui: adsk.core.UserInterface = None
_handlers = []

_facesIpt: adsk.core.SelectionCommandInput = None
_infoIpt: adsk.core.TextBoxCommandInput = None

DEBUG = False

class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandCreatedEventArgs):
        dumpMsg(args.firingEvent.name)
        try:
            global _handlers
            cmd: adsk.core.Command = adsk.core.Command.cast(args.command)
            inputs: adsk.core.CommandInputs = cmd.commandInputs

            # inputs
            global _facesIpt
            _facesIpt = inputs.addSelectionInput(
                '_facesIptId',
                'faces',
                'select faces'
            )
            _facesIpt.setSelectionLimits(0)
            _facesIpt.addSelectionFilter(adsk.core.SelectionCommandInput.Faces)

            global _infoIpt
            _infoIpt = inputs.addTextBoxCommandInput(
                '_infoIptId',
                'total area',
                '-',
                1,
                True
            )

            # event
            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            onExecute = MyExecuteHandler()
            cmd.execute.add(onExecute)
            _handlers.append(onExecute)

            onInputChanged = MyInputChangedHandler()
            cmd.inputChanged.add(onInputChanged)
            _handlers.append(onInputChanged)

            onValidateInputs = MyValidateInputsHandler()
            cmd.validateInputs.add(onValidateInputs)
            _handlers.append(onValidateInputs)

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


class MyValidateInputsHandler(adsk.core.ValidateInputsEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.ValidateInputsEventArgs):
        dumpMsg(args.firingEvent.name)

        global _facesIpt
        if _facesIpt.selectionCount < 1:
            args.areInputsValid = False


class MyInputChangedHandler(adsk.core.InputChangedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.InputChangedEventArgs):
        dumpMsg(args.firingEvent.name)

        global _facesIpt, _infoIpt
        if args.input != _facesIpt:
            return

        if _facesIpt.selectionCount < 1:
            _facesIpt.commandPrompt = 'select faces'
            _infoIpt.text = '-'
            return

        megArea = getTotalArea()

        _facesIpt.commandPrompt = f'total area:{megArea}'
        _infoIpt.text = megArea


class MyExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandEventArgs):
        dumpMsg(args.firingEvent.name)

        area = getTotalArea()
        exportText(area)


class MyCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandEventArgs):
        dumpMsg(args.firingEvent.name)
        adsk.terminate()


def dumpMsg(s):
    if not DEBUG:
        return

    global _app
    _app.log(f'{s}')
    print(s)


def getTotalArea() -> str:
    global _facesIpt
    area = 0
    for idx in range(_facesIpt.selectionCount):
        face: adsk.fusion.BRepFace = _facesIpt.selection(idx).entity
        area += face.area

    global _app
    unitMgr: adsk.core.UnitsManager = _app.activeProduct.unitsManager

    defUnits = unitMgr.defaultLengthUnits
    units = unitMgr.formatUnits(f'{defUnits}*{defUnits}')

    value = unitMgr.convert(area, unitMgr.internalUnits, units)
    return unitMgr.standardizeExpression(str(value), units)


def exportText(txt: str):
    def getExportPath() -> str:
        dlg: adsk.core.FileDialog = _ui.createFileDialog()
        dlg.title = 'export'
        dlg.isMultiSelectEnabled = False
        dlg.filter = 'Text File(*.txt)'

        if dlg.showSave() != adsk.core.DialogResults.DialogOK:
            return ''

        return dlg.filename

    # ****
    path = getExportPath()
    if len(path) < 1:
        return

    with open(path, 'w', newline="") as f:
        f.write(txt)


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

        cmdDef: adsk.core.CommandDefinition = _ui.commandDefinitions.itemById(
            'kantoku_total_area_cmd'
        )

        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(
                'kantoku_total_area_cmd',
                'total_area',
                'total_area'
            )

        global _handlers
        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)

        cmdDef.execute()

        adsk.autoTerminate(False)

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

 

Message 3 of 6
j4n.vokurka
in reply to: kandennti

Thank you,
I see what I should take a look at now 🙂

I meant it like this.
User can:
- select a face on a 3D model, change a color of the surface (face), can export an area of coloured surfaces to a local file

Message 4 of 6
kandennti
in reply to: j4n.vokurka

@j4n.vokurka .

 

I understand what you mean.
Please give me some time due to the difficulty.

Message 5 of 6
kandennti
in reply to: j4n.vokurka

@j4n.vokurka .

 

Due to its large size, the file is attached.

It colors the faces only during the process of selecting faces, but returns to the original color after the command is executed.

 

The exported file looks like this.

name,count,area
red,1,100.0 mm^2
green,2,200.0 mm^2
blue,3,300.0 mm^2
total,6,600.0 mm^2
Message 6 of 6
j4n.vokurka
in reply to: kandennti

Great, this is how it should work. I hope that won't be a problem. Alternatively screenshots should be sufficient. Thank you again for your time and quick response.👍

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report