Hi @echatzief -San.
I believe this is probably a continuation of this one.
https://forums.autodesk.com/t5/fusion-360-api-and-scripts/pocket-2d-operation-causes-fusion-360-to-c...
I came up with the idea this morning to use the outer product of the tangent of the outer edge of the target and the normal of the surface to make the determination.
It is long, but it is the is_outside function that is directly making the determination.
# Fusion360API Python script
import traceback
import adsk.core as core
import adsk.fusion as fusion
import adsk.cam as cam
def run(context):
ui: core.UserInterface = None
try:
app: core.Application = core.Application.get()
ui = app.userInterface
camObj: cam.CAM = get_cam_product()
# setup
setup: cam.Setup = get_setup(camObj)
if not setup: return
# axisZ
axisZ: core.Vector3D = core.Vector3D.create(0,0,1)
# tool
tool: cam.Tool = camObj.documentToolLibrary[0]
# body
prm: cam.CAMParameter = setup.parameters.itemByName("job_model")
body: fusion.BRepBody = list(prm.value.value)[0]
# get target faces
faces = get_planer_face(
body,
axisZ,
)
# create pocket2d
for face in faces:
create_pocket2d(setup, tool, face)
# generate
camObj.generateAllToolpaths(True)
except:
if ui:
ui.messageBox("Failed:\n{}".format(traceback.format_exc()))
def create_pocket2d(
setup: cam.Setup,
tool: cam.Tool,
face: fusion.BRepFace,
) -> None:
input: cam.OperationInput = setup.operations.createInput('pocket2d')
input.tool = tool
edges = get_outer_loop_edges(face)
edge: fusion.BRepEdge = edges[0]
contourParam: cam.CadContours2dParameterValue = input.parameters.itemByName(
'pockets'
).value
curveSelections: cam.CurveSelections = contourParam.getCurveSelections()
chain: cam.CurveSelection = curveSelections.createNewChainSelection()
chain.isReverted = is_outside(face, edge)
chain.inputGeometry = [edge]
contourParam.applyCurveSelections(curveSelections)
setup.operations.add(input)
def is_outside(
face: fusion.BRepFace,
edge: fusion.BRepEdge,
) -> bool:
startPnt: core.Point3D = edge.startVertex.geometry
eva: core.CurveEvaluator3D = edge.evaluator
_, prm = eva.getParameterAtPoint(startPnt)
tangent: core.Vector3D = None
_, tangent = eva.getTangent(prm)
normal: core.Vector3D = get_normal(face)
vec: core.Vector3D = normal.crossProduct(tangent)
vec.scaleBy(0.0001)
pnt: core.Point3D = startPnt.copy()
pnt.translateBy(vec)
tmpMgr: fusion.TemporaryBRepManager = fusion.TemporaryBRepManager.get()
faceBody: fusion.BRepBody = tmpMgr.copy(face)
res: fusion.PointContainment = faceBody.pointContainment(pnt)
return res == fusion.PointContainment.PointOutsidePointContainment
def get_outer_loop_edges(
face: fusion.BRepFace
) -> list[fusion.BRepEdge]:
loop: fusion.BRepLoop = None
for loop in face.loops:
if loop.isOuter:
return list(loop.edges)
return None
def get_normal(
face: fusion.BRepFace
) -> core.Vector3D:
normal: core.Vector3D = face.geometry.normal
if face.isParamReversed:
normal.scaleBy(-1)
return normal
def get_planer_face(
body: fusion.BRepBody,
axisZ: core.Vector3D,
) -> list[fusion.BRepFace]:
face: fusion.BRepFace = None
return [face for face in body.faces
if is_target_face(face, axisZ)]
def is_target_face(
face: fusion.BRepFace,
axisZ: core.Vector3D,
) -> bool:
if face.geometry.objectType != core.Plane.classType():
return False
normal: core.Vector3D = get_normal(face)
return axisZ.isEqualTo(normal)
def get_setup(camObj: cam.CAM) -> cam.Setup:
setups: cam.Setups = camObj.setups
if setups.count < 1:
return None
return setups[0]
def get_cam_product() -> cam.CAM:
app: core.Application = core.Application.get()
activete_cam_env()
return app.activeProduct
def activete_cam_env() -> None:
app: core.Application = core.Application.get()
ui: core.UserInterface = app.userInterface
camWS: core.Workspace = ui.workspaces.itemById('CAMEnvironment')
camWS.activate()
I have been able to successfully determine this with some modifications to your sample model, but I have not tested it enough and may find a counterexample.

There may be an easier way to determine this.