Body's distance to a ConstructionPlane

Body's distance to a ConstructionPlane

MichaelT_123
Advisor Advisor
673 Views
3 Replies
Message 1 of 4

Body's distance to a ConstructionPlane

MichaelT_123
Advisor
Advisor

Hi TF360,

 

Could you please check the functionality of MeasureManager?

 

Based on the generous combination of object types (as per Reference), the measurements could assess a body's distance to a construction plane.

 

Measure_BodyToCPlane.png

Unfortunately, my attempts have failed… in both cases conducted via UI as well as using a respective script by calling:

  measureResult = app.measureManager.measureMinimumDistance( CPlane, targetBody )

 

 

Regards

MichaelT

 

PS.

I am posting this problem concurrently on Design and Script forums as the problem seems to overlap the interests of both.

MichaelT
674 Views
3 Replies
Replies (3)
Message 2 of 4

kandennti
Mentor
Mentor

Hi @MichaelT_123 .

 

I have also experienced this, and I think it is probably a bug.

As an alternative, I created a temporary surface and tried to get the MinimumDistance.

# Fusion360API Python script
import adsk.core, adsk.fusion, traceback

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

        targetBody :adsk.fusion.BRepBody = root.bRepBodies[0]
        CPlane :adsk.fusion.ConstructionPlane = root.constructionPlanes[0]

        res :adsk.core.MeasureResults = getMinimumDistancePlane2Body(CPlane, targetBody)

        unitsMgr = des.unitsManager
        defLenUnit = unitsMgr.defaultLengthUnits
        dist = unitsMgr.convert(res.value, unitsMgr.internalUnits, defLenUnit)

        ui.messageBox(f'{targetBody.name} - {CPlane.name}\n{dist} {defLenUnit}')

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

def getMinimumDistancePlane2Body(
    constructionplane :adsk.fusion.ConstructionPlane,
    bRepBody :adsk.fusion.BRepBody) -> adsk.core.MeasureResults:

    app = adsk.core.Application.get()
    doc = app.activeDocument

    tmpDoc :adsk.fusion.FusionDocument = app.documents.add(
        adsk.core.DocumentTypes.FusionDesignDocumentType)

    des :adsk.fusion.Design = app.activeProduct
    des.designType = adsk.fusion.DesignTypes.DirectDesignType

    root :adsk.fusion.Component = des.rootComponent

    try:
        tmpMgr = adsk.fusion.TemporaryBRepManager.get()
        clone = root.bRepBodies.add(tmpMgr.copy(bRepBody))

        plane = constructionplane.geometry.copy()
        vecU :adsk.core.Vector3D = plane.uDirection
        vecV :adsk.core.Vector3D = plane.vDirection

        measureMgr = app.measureManager
        bBox = measureMgr.getOrientedBoundingBox(clone, vecU, vecV)
        vecNormal :adsk.core.Vector3D = vecU.crossProduct(vecV)
        infiniteLine = adsk.core.InfiniteLine3D.create(bBox.centerPoint, vecNormal)

        center = plane.intersectWithLine(infiniteLine)
        circle = adsk.core.Circle3D.createByCenter(center, vecNormal, 10000000)

        tmpMgr = adsk.fusion.TemporaryBRepManager.get()
        wires, _ = tmpMgr.createWireFromCurves([circle])
        tempBrep = tmpMgr.createFaceFromPlanarWires([wires])
        tmpFace = root.bRepBodies.add(tempBrep)

        return measureMgr.measureMinimumDistance(clone, tmpFace)
        
    except:
        pass

    finally:
        doc.activate()
        tmpDoc.close(False)

There may be an easier way.

Message 3 of 4

MichaelT_123
Advisor
Advisor

Konnichiwa Kandennti-san,

 

The code is impressive. Particularly, I find the use of measureMgr.getOrientedBoundingBox(clone, vecU, vecV)

very innovative. 👍

However, there are some issues here:

  1. It is a hard yakka for most of the mortals… particularly those on a wheat diet
  2. The crucial operations such as measurements in respectable CAD software should be performed at the software's core level.
  3. Moving such calculations to semi-effective external processes (high-level languages) leads to inefficiencies and inconsistencies, not to mention frustrations… of some.
  4. I hope that the measurement of the body to a plane combination is only the TF360-mishap in the case code statement.  

In this particular case, I used a relatively simple remedy (file:BodyDistance, sketch:CPlane):

  1. Create a sketch on CPlane
  2. Draw on it circle profile (CProfile) with a radius order of magnitude higher than the maximum dimension of targetBody.
  3. Perform the measurement as usual in UI. In the script, use : 
  4. measureResult = app.measureManager.measureMinimumDistance( CProfile, targetBody )

 

On a side note…

The distance measurements in any CAD software creates the foundation of the whole pyramid of successive processes. The consistency, type range and its speed are a critical determinant of the software. Much more, if the quality and pace of the operation are high enough, the design itself could gain a property of self-awareness, resulting in the interaction with the software to entirely different levels.

So how to improve the process?

The short and straightforward answer is: match an efficient algorithm with optimal utilization of the computing hardware.  Just as a mental health exercise (and shaking off the rust from some neurons), please find an outline of such an algorithm for measuring the body's distance to a plane (file BodyDistance).

The draft of steps is as follows (without possible optimizations):

  1. Create tempPlane_0 perpendicular to CPlane (there are an unlimited possibility here, which one is not essential)
  2. Project targetBody on the sketch references by tempPlane_0 (call it projection_0)
  3. Create tempPlane_1 perpendicular to tempPlane_0 (there are an unlimited possibility here, which one is not essential)
  4. Project projection_0 on the sketch references by tempPlane_1 (call it projection_1). Note that the projection_1 is a projection to a line (1D projection)
  5. Order the points coordinate (only one, it is 1D set).
  6. Relate endpoints (coordinates) to CPlane, giving you the maximum and minimum distance of the targetBody to CPlane.

BodyDistance.png

It is worth noting that the most computing-intensive operations (point 2 and 4) can be combined as one algebraic matrix operations. As such, it opens the way to unleash possibilities of parallel processing on CPU or even better on GPU (particularly if the model resides on its memory). Given the current hardware abilities, there is a chance that the speed of the operations would be sufficient to achieve …. a design self-awareness paradigm (e.g. bumping objects).

 

Regards

MichaelT

 

MichaelT
0 Likes
Message 4 of 4

kandennti
Mentor
Mentor

@MichaelT_123 .

 

After thinking about it, I realized that it was possible to measure without creating a useless surface.

 

# Fusion360API Python script
import adsk.core, adsk.fusion, traceback

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

        targetBody :adsk.fusion.BRepBody = root.bRepBodies.itemByName('targetBody')
        CPlane :adsk.fusion.ConstructionPlane = root.constructionPlanes.itemByName('CPlane')

        res = getMinimumDistancePlane2Body(CPlane, targetBody)

        unitsMgr = des.unitsManager
        defLenUnit = unitsMgr.defaultLengthUnits
        dist = unitsMgr.convert(res, unitsMgr.internalUnits, defLenUnit)

        ui.messageBox(f'{targetBody.name} - {CPlane.name}\n{dist} {defLenUnit}')

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

def getMinimumDistancePlane2Body(
    constructionplane :adsk.fusion.ConstructionPlane,
    bRepBody :adsk.fusion.BRepBody) -> float:

    app = adsk.core.Application.get()

    plane = constructionplane.geometry
    vecU :adsk.core.Vector3D = plane.uDirection
    vecV :adsk.core.Vector3D = plane.vDirection

    measureMgr = app.measureManager
    bBox = measureMgr.getOrientedBoundingBox(bRepBody, vecU, vecV)

    infiniteLine = adsk.core.InfiniteLine3D.create(bBox.centerPoint, plane.normal)
    pnt = plane.intersectWithLine(infiniteLine)

    res = measureMgr.measureMinimumDistance(bBox.centerPoint, pnt)
    dist = res.value - (bBox.height * 0.5)

    return dist if dist > 0 else 0

 

0 Likes