Find any interferance with active objects and only one 'tool' object.

Find any interferance with active objects and only one 'tool' object.

zxynine
Enthusiast Enthusiast
1,554 Views
8 Replies
Message 1 of 9

Find any interferance with active objects and only one 'tool' object.

zxynine
Enthusiast
Enthusiast

I was searching for a while for an api focused version of this question(Finding Intersecting or Overlapping Bodies and Components) that is really only worried about a specific body. Essentially I was looking to implement a version of an extrude and so I want to know what bodies in the scene a specific object happens to overlap with. I have not seen any version which is focuses on only one objects interaction with others, instead it seems to be all objects overlapping.

I originally wanted it to just look for any intersection with any active objects in the scene, but I figured, with how quickly scenes can scale up, and the interference tool not being optimised for this specific case, it was best to keep the scope down. Currently my solution is to take bodies connected to the objects im "extruding"(I end up creating seperate objects i use the combine feature with) and run the interference calc on all of them and then filter the results based on if the cutting tool is one of the interference objects in each result. This seems very obtuse for what im trying to do and it does not allow for the "extrudes" to cut objects that it did not originally create them. Are there any better methods of doing this that I have overlooked? I have yet to find much information on doing this sort of stuff.

 

Additionally, if anyone else is looking for how to do it, my code is below. A quick note on it, utils.Collections.join is just a function that creates an objectcollection from multiple iterable objects and utils.Items is a function that just returns a list of the items in a collection which are properly type hinted (bracket access does not type hint the return, instead collection.item() would be used) so those functions are really just to make my life easier and dont change how the code works.

def findIterferances(targetBodies:'list[adsk.fusion.BRepBody]', toolBodies:'list[adsk.fusion.BRepBody]'):
	interferanceCollection = utils.Collections.join(targetBodies,toolBodies)
	interferanceInput = design.createInterferenceInput(interferanceCollection)
	interferanceResults = utils.Items(design.analyzeInterference(interferanceInput))

	ToolIntersections:'list[adsk.fusion.BRepBodies,adsk.fusion.BRepBodies]' = []
	for result in interferanceResults:
		if result.entityOne in toolBodies: ToolIntersections.append((result.entityOne,result.entityTwo))
		elif result.entityTwo in toolBodies: ToolIntersections.append((result.entityTwo,result.entityOne))
	return ToolIntersections

 

0 Likes
1,555 Views
8 Replies
Replies (8)
Message 2 of 9

kandennti
Mentor
Mentor

Hi @zxynine .

 

This isn't a question, is it?
I didn't understand what "utils" indicated.

 

If it is body-to-body interference, you can use TemporaryBRepManager.imprintOverlapBodies method to do it.

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-87400208-7F2B-4931-A707-E75BD7A85776 

0 Likes
Message 3 of 9

zxynine
Enthusiast
Enthusiast

Hey, the top two paragraphs are the actual question, my third is my providing the solution I currently am using for other people to use who are in the same situation as me. The “Utils” I was talking about are my own personal utilities module, and I was trying to tell people what those functions did so they can modify the code to work for them.

0 Likes
Message 4 of 9

zxynine
Enthusiast
Enthusiast

I took a look at the temporaryBrepManager function you provided, I think it is a really interesting tool that could help speed things up to some degree since it would no longer calculate an overlap between every object, however I don’t know if it would be too much faster since I would still need to search each body in the scene and calculate the temporary body for every one of them through the api myself. I will definitely look into it more in the morning I only recently have gotten around to looking into the temporary brep manager in the first place. I do not know if it can be directly used in something like a combine feature or if I need to create the body in file and then do it to preserve the parametric adjustability I would like. If I need to do that, then I don’t think it’ll be much faster since anything done in the api will be far slower than native fusion functions. I’m using python and that itself is already 4x slower than a compiled language such as c#

0 Likes
Message 5 of 9

kandennti
Mentor
Mentor

@zxynine .

 

Since I had never tried it before, I made a sample and compared it.

The imprintOverlapBodies method was much slower, and there were many oversights.
I may be doing something wrong.

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core
import random

import itertools
import time


def run(context):
    ui: adsk.core.UserInterface = None
    try:
        app: adsk.core.Application = adsk.core.Application.get()
        ui = app.userInterface
        app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)

        # create Sphere bodies
        initSpheres(100)
        app.activeViewport.fit()

        # get All bodies shown
        des: adsk.fusion.Design = app.activeProduct
        root: adsk.fusion.Component = des.rootComponent
        objs: adsk.core.ObjectCollection = root.findBRepUsingPoint(
            adsk.core.Point3D.create(0, 0, 0),
            adsk.fusion.BRepEntityTypes.BRepBodyEntityType,
            xxx-xxxxxxxx,
            True
        )
        bodies = [b for b in objs]

        ui.messageBox('Find combinations of intersecting bodies.')

        # start collision check
        app.log(u'TextCommandWindow.Clear')

        # imprintOverlapBodies
        app.log('-- start imprintOverlapBodies --')
        t = time.time()
        collisionLst = find_Collision_Bodies(bodies)
        msg = f'Count {len(collisionLst)} : time {time.time() -t}s'
        app.log('\n'.join(collisionLst))
        app.log(msg)

        app.log('\n-- start analyzeInterference --')
        t = time.time()
        collisionLst = find_Interference_Bodies(objs)
        msg = f'Count {len(collisionLst)} : time {time.time() -t}s'
        app.log('\n'.join(collisionLst))
        app.log(msg)

        ui.messageBox('Done')

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


def find_Interference_Bodies(
        bodies: adsk.core.ObjectCollection) -> list:

    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct

    interferanceResults: adsk.fusion.InterferenceResults = des.analyzeInterference(
        des.createInterferenceInput(bodies)
    )

    return [f'{res.entityOne.name} - {res.entityTwo.name}' for res in interferanceResults]


def find_Collision_Bodies(
        bodies: list) -> list:

    combs = itertools.combinations(bodies, 2)
    tmpMgr: adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get()
    collisionLst = []
    for b1, b2 in combs:
        _, _, _, bodyOneOverlappingFaces, bodyTwoOverlappingFaces, _, _ = tmpMgr.imprintOverlapBodies(
            b1,
            b2,
            True)
        if len(bodyOneOverlappingFaces) + len(bodyTwoOverlappingFaces) > 0:
            collisionLst.append(f'{b1.name} - {b2.name}')
    return collisionLst


def initSpheres(count: int):
    radius = 1
    posMin = 0
    posMax = 8

    # points
    pnts = []
    for _ in range(count):
        pnts.append(
            adsk.core.Point3D.create(
                random.randrange(posMin, posMax),
                random.randrange(posMin, posMax),
                random.randrange(posMin, posMax),
            )
        )

    # temp bodies
    tmpMgr: adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get()

    sphereBodies: list = []
    pnt: adsk.core.Point3D
    for pnt in pnts:
        sphere: adsk.fusion.BRepBody = tmpMgr.createSphere(pnt, radius)
        sphereBodies.append(sphere)

    # brep bodies
    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct
    root: adsk.fusion.Component = des.rootComponent

    baseFeat: adsk.fusion.BaseFeature = root.features.baseFeatures.add()
    bodies: adsk.fusion.BRepBodies = root.bRepBodies
    baseFeat.startEdit()
    for body in sphereBodies:
        bodies.add(body, baseFeat)
    baseFeat.finishEdit()
0 Likes
Message 6 of 9

j.han97
Advocate
Advocate

I did not fully understand your question: Are you trying to find intersections that involve ONE specific body? And your concern is that the number of bodies could be very large and applying the intersection calculator on all of them would be inefficient.

 

If that's the case (assume that I understood correctly), I would suggest using the boundingBox property to check for other bodies whose bounding boxes intersect with your target body's box. From my experience this is a quick way to find the entities that are close to the target. 

Message 7 of 9

zxynine
Enthusiast
Enthusiast

I think you got it, essentially I want to know every active body in the scene and then do the interference calculation between just a few specific "tool" objects and all of those active objects so that I can create a combine feature and essentially remove the area that the tool overlaps with. I was just playing around in fusion now and I noticed the cut operation on an extrusion vs new body has a significant performance difference so id reckon there isn't much of a way to get around that sadly. I do like the idea of using the bounding boxes to rule out many components though. I wonder if I can skip the interference calculation entirely and just use the combine feature and all nearby bodies to save on performance since combine must use some form of interference calculation itself. I will need to do more testing.

0 Likes
Message 8 of 9

zxynine
Enthusiast
Enthusiast
Sadly, I believe it to be a limitation of the temporary brep manager (lets call it TBM since im lazy). The TBM, at least from what i know, is very good at doing calculations for breps and their operations when you dont need to render any of the bodies you are using. I would imagine that, creating a temp BRep then converting that to a standard Brep will take a bit longer than directly creating a BRep since you have to go through two layers of functions, but it is made up for in the fact that Temp Breps are not rendered and therefore you can move them and change them with little strain on the graphics engine to display them which saves time. Since what we are trying to do is find overlaps and then create cuts from that, I dont think the TBM is actually designed for such short term use, but this is all mostly speculation on my part.
0 Likes
Message 9 of 9

kandennti
Mentor
Mentor

@zxynine .

 

I don't understand it fully because I don't understand English.

Do you want to create a Body that only interferes with targetBodies and toolBodies?

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core
import random
import time


def run(context):
    ui: adsk.core.UserInterface = None
    try:
        app: adsk.core.Application = adsk.core.Application.get()
        ui = app.userInterface
        app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)

        # create Sphere bodies
        initSpheres(100)
        app.activeViewport.fit()

        # get All bodies shown
        des: adsk.fusion.Design = app.activeProduct
        root: adsk.fusion.Component = des.rootComponent
        objs: adsk.core.ObjectCollection = root.findBRepUsingPoint(
            adsk.core.Point3D.create(0, 0, 0),
            adsk.fusion.BRepEntityTypes.BRepBodyEntityType,
            1000000000,
            True
        )
        bodies = [b for b in objs]
        targetBodies = bodies[:10]
        toolBodies = bodies[11:]

        ui.messageBox('Find combinations of intersecting bodies.')

        # start analyzeInterference
        app.log(u'TextCommandWindow.Clear')
        app.log('\n-- start analyzeInterference --')
        t = time.time()

        interBodies = findIterferances(targetBodies, toolBodies)

        # Result
        occ: adsk.fusion.Occurrence = root.occurrences.addNewComponent(
            adsk.core.Matrix3D.create()
        )
        occ.component.name = 'Interference Result'

        baseFeat: adsk.fusion.BaseFeature = occ.component.features.baseFeatures.add()
        bodies: adsk.fusion.BRepBodies = occ.component.bRepBodies
        baseFeat.startEdit()
        for body in interBodies:
            bodies.add(body, baseFeat)
        baseFeat.finishEdit()

        msg = f'Count {len(interBodies)} : time {time.time() -t}s'
        app.log(msg)

        ui.messageBox('Done')

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


def findIterferances(
    targetBodies: 'list[adsk.fusion.BRepBody]',
    toolBodies: 'list[adsk.fusion.BRepBody]') -> 'list[adsk.fusion.BRepBody]':

    bodyObjs: adsk.core.ObjectCollection = adsk.core.ObjectCollection.create()
    [bodyObjs.add(b) for b in targetBodies]
    [bodyObjs.add(b) for b in toolBodies]

    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct

    interferanceResults: adsk.fusion.InterferenceResults = des.analyzeInterference(
        des.createInterferenceInput(bodyObjs)
    )

    interBodies = []
    res: adsk.fusion.InterferenceResult
    for res in interferanceResults:
        if res.entityOne in targetBodies or res.entityTwo in targetBodies:
            interBodies.append(res.interferenceBody)

    return interBodies

def initSpheres(count: int):
    radius = 1
    posMin = 0
    posMax = 8

    # points
    pnts = []
    for _ in range(count):
        pnts.append(
            adsk.core.Point3D.create(
                random.randrange(posMin, posMax),
                random.randrange(posMin, posMax),
                random.randrange(posMin, posMax),
            )
        )

    # temp bodies
    tmpMgr: adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get()

    sphereBodies: list = []
    pnt: adsk.core.Point3D
    for pnt in pnts:
        sphere: adsk.fusion.BRepBody = tmpMgr.createSphere(pnt, radius)
        sphereBodies.append(sphere)

    # brep bodies
    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct
    root: adsk.fusion.Component = des.rootComponent

    baseFeat: adsk.fusion.BaseFeature = root.features.baseFeatures.add()
    bodies: adsk.fusion.BRepBodies = root.bRepBodies
    baseFeat.startEdit()
    for body in sphereBodies:
        bodies.add(body, baseFeat)
    baseFeat.finishEdit()

I think this is faster than TemporaryBRepManager.