Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Exception raised on evaluator.getPointsAtParameters from parameters given by ev.

7 REPLIES 7
Reply
Message 1 of 8
gscotti
310 Views, 7 Replies

Exception raised on evaluator.getPointsAtParameters from parameters given by ev.

This is the failing code:

           ev = curve.geometry.evaluator
            ret, params = ev.getParametersAtPoints(points)
            if not ret:
                raise AttributeError('invalid points in getParametersAtPoints')

            print(params,curve.geometry)
            ret, pts = ev.getPointsAtParameters(params)
            if not ret:
                raise AttributeError('invalid points in getPointsAtParameters')

I've attached the model I'm trying it with. Sketch1 works (circles) but Sketch2 fails (rectangles.

 

7 REPLIES 7
Message 2 of 8
ekinsb
in reply to: gscotti

The API exposes some underlying math and geometry tools and we get whatever their native behavior is.  In this case it appears that the getParameterAtPoints ignores the limits of the curve and returns parameters as if the curve was not bounded.  For example, it treats a line as infinite length and an arc as a circle.  But the getPointAtParameter expects the input parameter to be within the bounded portion of the curve and that's why it's failing.  I modified your function so it now checks if the parameter is within the bounded range and if not, adjusts it to the closest end.  I tried on various shapes and it seems to work now.

 

    def findClosestPoints(self, points):
        n = len(points)
        ptsOnCurve = [{} for i in range(n)]
        for curve in self.curves:
            ev = adsk.core.CurveEvaluator3D.cast(curve.geometry.evaluator)
            ret, minExtent, maxExtent = ev.getParameterExtents()

            ret, params = ev.getParametersAtPoints(points)
            if not ret:
                raise AttributeError('invalid points in getParametersAtPoints')

            newParams = []
            for param in params:
                if param < minExtent:
                    newParams.append(minExtent)
                elif param > maxExtent:
                    newParams.append(maxExtent)
                else:
                    newParams.append(param)

            print(params,curve.geometry)
            if len(newParams) > 0:
                ret, pts = ev.getPointsAtParameters(newParams)
                if not ret:
                    raise AttributeError('invalid points in getPointsAtParameters')
    
                for i in range(n):
                    d = points[i].distanceTo(pts[i])
                    ptsOnCurve[i][d] = (pts[i],curve)

        # query min points
        output = []
        if len(ptsOnCurve[0]) > 0:
            for i in range(n):
                dmin = min(ptsOnCurve[i])
                pt,curve = ptsOnCurve[i][dmin]
                output.append((pt,curve))

        return output

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 3 of 8
gscotti
in reply to: ekinsb

I ended up doing the same as you did. However, you are expected to get valid data from the API functions, don't you think?

 

Message 4 of 8
ekinsb
in reply to: gscotti

I think this is a case where "valid" is left up to some interpretation so returning a parameter on the boundless curve can be considered valid and it could be used to determine if the input point is one the curve or outside.  Whereas if we were to adjust the parameters to the bounded portion you couldn't do that.  But returning parameters within the bounded extents could also be considered "valid".  Regardless, of what we consider to be "correct", we'll leave the behavior the way it is in case people have taken advantage of the current behavior and we don't want to break them.  I will make a note to add some additional information to the documentation about the behavior though.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 5 of 8
gscotti
in reply to: ekinsb

I agree with your argument. However, getPointsAtParameters contradicts it.

Let me explain it better:

  getParametersAtPoint(pt) returns parameters beyond the curve, as you explained.

 

Using the same argument as you did, why getPointsAtParameters validates the parameters if its inverse function allows to return parameters beyond its curve extents? That sounds like contradictory. I would love to have both functions returning parameters beyond the curve. That's the whole point about parametrized curves, right?

 

 

Message 6 of 8
gscotti
in reply to: gscotti

And I hope you don't change the behavior of getParametersAtPoints, because I've been using it to get closest point at curves, for the lack of a better function. Which is not exactly the way you describe its purpose is. Is it correct to say "..could be used to determine if the input point is beyond the curve or not." Because is 'on' or 'outside' the curve is a open to interpretations.
Message 7 of 8
ekinsb
in reply to: gscotti

I agree that there is some contradiction in the behavior.  As I said, the API is using a general geometry and math library (actually AcGe which comes from AutoCAD) and we get that library's native behavior.  However, I just looked at the API source code and we're adding an extra check in getPointsAtParameters to validate if the input parameter is on the curve and if it's not it fails with the "invalid argument parameters" error.  So getPointsAtParameters cares about the bounds and getParametersAtPoint doesn't.  But I would be hesitant to change the behavior at this point but we should document it.

 

And yes, saying the point is "beyond the curve or not" is probably a better way to say it.  Anytime the point is off the curve though there could be some unexpected results for some cases.  For a line or arc it's simple because a boundless arc is always a circle and a boundless line is known.  However a spline can't necessarily be extended to infinity and can curve in unexpected ways when it is extended.  And it's possible there could be multiple correct answers.  For example, what parameter should be returned if you input the center point of a circle for the circle?  I know these are not typical cases but I'm just trying to say that it's best to use points that lie very near the curve to get the best results.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 8 of 8
gscotti
in reply to: ekinsb

Understood. I believe the whole point is that getParametersAtPoints should not return any parameter outside its parameters limits. From parametric math perspective, that's wrong, because the returned value is not within the curve's domain. Perhaps the whole point is to think that a bounded line is an infinite line, which in this case it is not.

 

 

To answer your question: I expect to get any parameter from the parametric circle if I give origin as reference point. Same thing happens if set any point inside the circle: you have two possible points, and whichever is returned is what I would expect as a valid answer. That's actually a good test case for the API. 🙂

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report