Reply
Highlighted
Participant
10 Posts
Accepted Solution

sketchArcs.addFillet failing between two sketchArc objects

64 Views, 4 Replies
a month ago

Might be related to https://forums.autodesk.com/t5/api-and-scripts/addfillet-in-sketchmode-between-a-line-and-arc/m-p/65...

 

I'm iterating through sketch to find all sketch points where an arc joins another arc or line, and trying to add a fillet between the two.

 

When it tries to add fillet between two Arcs it fails (I'm using sketchPoint.connectedEntities, but checking to make sure the connection is due to start/end rather than arc center). If I modify the code to only try fillets at points where a sketchArc meets a sketchLine it works.

 

 

points_to_fillet = []
for p in sketch.sketchPoints:
	if p.connectedEntities and p.connectedEntities.count == 2:
		if p.connectedEntities[0].classType()=="adsk::fusion::SketchArc" or p.connectedEntities[1].classType()=="adsk::fusion::SketchArc":
			if p.connectedEntities[0].startSketchPoint == p or p.connectedEntities[0].endSketchPoint == p:
				if p.connectedEntities[1].startSketchPoint == p or p.connectedEntities[1].endSketchPoint == p:
					points_to_fillet.append(p)
		
for p in points_to_fillet:
	e1, e2 = p.connectedEntities
	fillet_point = p.geometry
	sketch.sketchCurves.sketchArcs.addFillet(e1, fillet_point, e2, fillet_point, radius)

I used a bunch of debugging print statements to get coordinates of p as well as e1 and e2 start/end sketch points and it looks like it should work:

 

 

 

----------
point p
----------
<adsk.fusion.SketchPoint; proxy of <Swig Object of type 'adsk::core::Ptr< adsk::fusion::SketchPoint > *' at 0x1497228a0> >
x=1.139926523123076, y=9.246681703470033, z=0.0

----------
entity e1
----------
<adsk.fusion.SketchArc; proxy of <Swig Object of type 'adsk::core::Ptr< adsk::fusion::SketchArc > *' at 0x149722ba0> >
start: x=8.027898386072238, y=-2.683635524262752, z=0.0
end:   x=1.139926523123076, y=9.246681703470033, z=0.0

----------
entity e2
----------
<adsk.fusion.SketchArc; proxy of <Swig Object of type 'adsk::core::Ptr< adsk::fusion::SketchArc > *' at 0x149722c60> >
start: x=0.31749999999999995, y=7.457127787579157, z=0.0
end:   x=1.139926523123076, y=9.246681703470033, z=0.0

----------
radius
----------
r=0.127

 

 The arcs in question started out as sketchCircles that intersected and were trimmed - the problematic points are the unfilleted ones in the pic below, and they all fail with "RuntimeError: 3 : Failed to create fillet." (a more descriptive error message would be helpful!)

 

Screen Shot 2017-03-24 at 3.57.34 PM.png

 

Best regards,

 

Michael

 

The reason for the failure is because of the points you're using in the addFillet method.  You can't use the end point in your case because it's also the intersection point of the two curves. The picture below shows two lines on the left and two lines on the right.  In both cases there are four different possible fillets between the two curves are shown. 

 

FilletExamples.png

 

Giving the intersection point as the fillet point doesn't identify which of the four fillets to create. Instead you need a point close to the intersection, but on the portion of the curve that will be kept. In the picture below, if you provide a point anywhere along the red portion as the fillet point on the two curves, you'll end up with the highlighted fillet.

 

FilletLines.png

 

 

Here's a variation of your program that finds points very close to the intersection but off just a little bit in the direction of the other end of the curve. My algorithm assumes the curves are end point connected and not overlapping, which will always be the case in your problem because you're first finding the connected curves.

 

def run(context):
try:
global _app, _ui
_app = adsk.core.Application.get()
_ui = _app.userInterface
des = adsk.fusion.Design.cast(_app.activeProduct)
root = des.rootComponent
sketch = root.sketches.item(0)
points_to_fillet = []
for p in sketch.sketchPoints:
if p.connectedEntities and p.connectedEntities.count == 2:
if p.connectedEntities[0].classType()=="adsk::fusion::SketchArc" or p.connectedEntities[1].classType()=="adsk::fusion::SketchArc":
if p.connectedEntities[0].startSketchPoint == p or p.connectedEntities[0].endSketchPoint == p:
if p.connectedEntities[1].startSketchPoint == p or p.connectedEntities[1].endSketchPoint == p:
points_to_fillet.append(p)
p = adsk.fusion.SketchPoint.cast(None)
for p in points_to_fillet:
e1, e2 = p.connectedEntities
filletPoint1 = closePoint(p, e1)
filletPoint2 = closePoint(p, e2)
sketch.sketchCurves.sketchArcs.addFillet(e1, filletPoint1, e2, filletPoint2, 1.0)
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def closePoint(skPoint, skCurve):
isStart = False
if skPoint == skCurve.startSketchPoint:
isStart = True
curveEval = adsk.core.CurveEvaluator3D.cast(skCurve.geometry.evaluator)
(retVal, startParam, endParam) = curveEval.getParameterExtents()
if isStart:
paramEval = (endParam + startParam) * .05
else:
paramEval = (endParam + startParam) * .95
(retVal, pnt) = curveEval.getPointAtParameter(paramEval)
return(pnt)

 

 

 

 

 

Autodesk Support
1262 Posts
353 Kudos
369 Solutions

Re: sketchArcs.addFillet failing between two sketchArc objects

a month ago in reply to: michael

The reason for the failure is because of the points you're using in the addFillet method.  You can't use the end point in your case because it's also the intersection point of the two curves. The picture below shows two lines on the left and two lines on the right.  In both cases there are four different possible fillets between the two curves are shown. 

 

FilletExamples.png

 

Giving the intersection point as the fillet point doesn't identify which of the four fillets to create. Instead you need a point close to the intersection, but on the portion of the curve that will be kept. In the picture below, if you provide a point anywhere along the red portion as the fillet point on the two curves, you'll end up with the highlighted fillet.

 

FilletLines.png

 

 

Here's a variation of your program that finds points very close to the intersection but off just a little bit in the direction of the other end of the curve. My algorithm assumes the curves are end point connected and not overlapping, which will always be the case in your problem because you're first finding the connected curves.

 

def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface
        
        des = adsk.fusion.Design.cast(_app.activeProduct)
        root = des.rootComponent
        sketch = root.sketches.item(0)

        points_to_fillet = []
        for p in sketch.sketchPoints:
            if p.connectedEntities and p.connectedEntities.count == 2:
                if p.connectedEntities[0].classType()=="adsk::fusion::SketchArc" or p.connectedEntities[1].classType()=="adsk::fusion::SketchArc":
                    if p.connectedEntities[0].startSketchPoint == p or p.connectedEntities[0].endSketchPoint == p:
                        if p.connectedEntities[1].startSketchPoint == p or p.connectedEntities[1].endSketchPoint == p:
                            points_to_fillet.append(p)

        p = adsk.fusion.SketchPoint.cast(None)
        for p in points_to_fillet:
            e1, e2 = p.connectedEntities
            filletPoint1 = closePoint(p, e1)
            filletPoint2 = closePoint(p, e2)
                    
            sketch.sketchCurves.sketchArcs.addFillet(e1, filletPoint1, e2, filletPoint2, 1.0)
    except:
        if _ui:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def closePoint(skPoint, skCurve):
    isStart = False
    if skPoint == skCurve.startSketchPoint:
        isStart = True

    curveEval = adsk.core.CurveEvaluator3D.cast(skCurve.geometry.evaluator)
    (retVal, startParam, endParam) = curveEval.getParameterExtents()
    if isStart:
        paramEval = (endParam + startParam) * .05 
    else:
        paramEval = (endParam + startParam) * .95

    (retVal, pnt) = curveEval.getPointAtParameter(paramEval)
    return(pnt)

 

 

 

 

 


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Participant
10 Posts

Re: sketchArcs.addFillet failing between two sketchArc objects

a month ago in reply to: ekinsb

Hmm, I don't understand the difference between the line+curve case vs curve+curve case - in both, the intersection point is the endpoint.

 

My code works on this point:

 

Screen Shot 2017-03-31 at 11.32.22 AM.png

 

but fails on this point:

 

Screen Shot 2017-03-31 at 11.32.14 AM.png

 

The lines/curves end at the intersection point, I don't understand how Fusion 360 would see 4 possible fillets here. (and if so, why only in the 2nd case).

 

I will use the code modification to work around but it still seems like a bug to me!

 

Best regards,

 

Michael

Autodesk Support
1262 Posts
353 Kudos
369 Solutions

Re: sketchArcs.addFillet failing between two sketchArc objects

a month ago in reply to: michael

Good question about why lines would work and fillets don't.  I don't understand that either and apparently it's just a side-effect of how some things are computed internally.  I understand in your case there is only one obvious fillet, but the API needs to take care of the general case where you have two entities that aren't connected but cross over each other.  In that case there are four possible fillets and specifying the intersection point is ambiguous and doesn't identify which of the possible four results to create.  I agree that it would be best if it was smart enough to see that the curves are end connected and just create the single result but that's not the current behavior and by specifying a point along the curve instead of at the intersection you can get the desired result.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Participant
10 Posts

Re: sketchArcs.addFillet failing between two sketchArc objects

a month ago in reply to: ekinsb

Thanks, I used your code for grabbing a nearby point on the line and I've got all the desired fillets!

 

Best regards,

 

Michael