Hi @lionel.courgnaud .
I don't know the details, but it is possible to determine if a point is on a surface with SurfaceEvaluator.isParameterOnFace.
https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-e6682eb7-48f8-472d-9872-71da3c5ba8c8
Without relying on constraints, I calculated the three vertices of the rectangle and drew it with the sketchLines.addThreePointRectangle method.
https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-f2298d37-2ae0-4db8-8f8e-b374edb49213
# Fusion360API Python script
import traceback
import adsk.fusion
import adsk.core
import math
def run(context):
ui: adsk.core.UserInterface = None
try:
app: adsk.core.Application = adsk.core.Application.get()
ui = app.userInterface
rectangleSize = 0.34
offsetDistance = 0.2
msg: str = 'Select Sketch Line'
selFilter: str = 'SketchLines'
while(True):
sel: adsk.core.Selection = selectEnt(msg, selFilter)
if not sel:
return
sktLine: adsk.fusion.SketchLine = sel.entity
createRectangle(
sktLine,
rectangleSize,
offsetDistance
)
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def createRectangle(
sktLine: adsk.fusion.SketchLine,
rectangleSize: float,
offsetDistance: float):
# sketch
skt: adsk.fusion.Sketch = sktLine.parentSketch
axisZ: adsk.core.Vector3D = skt.xDirection.crossProduct(
skt.yDirection
)
# sketch support face
face: adsk.fusion.BRepFace = adsk.fusion.BRepFace.cast(
skt.referencePlane
)
if not face:
return
# offset vector
vecV: adsk.core.Vector3D = sktLine.geometry.asInfiniteLine().direction
vecV.normalize()
vecH: adsk.core.Vector3D = vecV.crossProduct(axisZ)
vecH.normalize()
# mid point
line: adsk.core.Line3D = sktLine.geometry
sPnt: adsk.core.Point3D = skt.sketchToModelSpace(line.startPoint)
ePnt: adsk.core.Point3D = skt.sketchToModelSpace(line.endPoint)
mPnt: adsk.core.Point3D = adsk.core.Point3D.create(
(sPnt.x + ePnt.x) * 0.5,
(sPnt.y + ePnt.y) * 0.5,
(sPnt.z + ePnt.z) * 0.5
)
# center vector
centerVec: adsk.core.Vector3D = vecH.copy()
centerVec.scaleBy(
rectangleSize * 0.5 + offsetDistance
)
# get center point on face
center: adsk.core.Point3D = None
eva: adsk.core.SurfaceEvaluator = face.evaluator
pnt: adsk.core.Point3D
vec: adsk.core.Vector3D
prm: adsk.core.Point2D
for scl in [1, -1]:
vec = centerVec.copy()
vec.scaleBy(scl)
pnt = mPnt.copy()
pnt.translateBy(vec)
_, prm = eva.getParameterAtPoint(pnt)
if eva.isParameterOnFace(prm):
center = pnt
break
if not center:
return
# Vector to the vertices
vec = vecV.copy()
vec.add(vecH)
vec.normalize()
vec.scaleBy(
rectangleSize * 0.5 * math.sqrt(2)
)
vertices = []
p: adsk.core.Point3D
for deg in [0, 90, 180]:
p = center.copy()
p.translateBy(vec)
mat: adsk.core.Matrix3D = adsk.core.Matrix3D.create()
mat.setToRotation(
math.radians(deg),
axisZ,
center
)
p.transformBy(mat)
# skt.modelToSketchSpace(p) #NG
mat = skt.transform.copy()
mat.invert()
p.transformBy(mat)
vertices.append(p)
# draw Rectangle
lines: adsk.fusion.SketchLines = skt.sketchCurves.sketchLines
lines.addThreePointRectangle(
vertices[0],
vertices[1],
vertices[2],
)
def selectEnt(
msg: str,
filterStr: str) -> adsk.core.Selection:
try:
app = adsk.core.Application.get()
ui = app.userInterface
sel = ui.selectEntity(msg, filterStr)
return sel
except:
return None