Curve Flip Error

I am working on a GhPython script and am running into an error with curve flipping. I want the direction of the curve to change- the start and end should swap places. The .Reverse() method seems to be flipping the tangent vector, but not the actual point on curve.

Both output a and b are in the same location rather than on opposite sides of the curve. I tried to use the flip component and am getting the same results. I’ve isolated the problem in the attached script.

160810 Curve Flip Problem.gh (7.5 KB)

So what you really want to do is mirror the curve, correct?

I took it to mean he wanted the original start point to become the end point and vice-versa, without changing the appearance. But maybe you’re right.

No, I want to flip the direction of the curve. I want the new start to be where the end used to be. I don’t want the curve to change or move.

Reversing a curve’s direction changes the curve’s domain from [a,b] to [-b,-a]. Thus, when you do this:

point = curve.PointAt(0)

‘point’ will be the same result whether the curve is reversed or not, given that ‘0’ falls within the curve’s domain.

If you need the starting and ending points of a curve, use:

start_pt = curve.PointAtStart
end_pt = curve.PointAtEnd

You can also do this:

start_pt = Curve.PointAt(curve.Domain.Min)
end_pt = Curve.PointAt(curve.Domain.Max)

Finally, unless you really need a NURBS curve, here is probably no reason to convert the Line to a NurbsCurve.

Hope this helps.

– Dale

When you use rg.Line things are different.

@MarcusStrube, your example is pretty good. But why are you normalizing the domain? The domain in this case should be correct.

Its not often that you need to reparameterize a curve or surface. Keep in mind that poorly parameterized objects may not intersect and trim properly when combined with other objects. “Poorly parameterized” means the curve’s domain or the surface’s u or v spaces are tiny or huge compared to the size of the object…

I’m in a situation where I do not want to have to redraw the curve. What is the best way to get temp2 to appear as if it was drawn as line from y to x (instead of x to y)? I don’t want to deal with negative domains.

Reversing the direction of a curve will not change it’s appearance - no redraw required.

Why does this matter?

You are right. I just hadn’t checked this and wanted to show how normalizing works.

Your solution worked for me. I was hoping there was some flip() method I was not seeing, but one extra line of code isn’t so bad.

So reparameterizing is something I’ve been curious about. In my example I only tried to get the start point on the curve, but that is not always the case. I almost always reparameterize my curves and surfaces so that I can work between 0:1. If I don’t reparameterize, how do I get a point at the middle or quarter from the start or quarter from the end? Would I have to get the domain, multiply by the fraction (.5, .25, .75) and then do .PointAt(t)?

Exactly, but Curve.Domain.Min is not always 0:

The magic is to use Curve.NormalizedLengthParameter to calculate a curve parameter at a normalized parameter. For example:

import Rhino.Geometry as geo

start_pt = geo.Point3d(2, 3, 4)
end_pt = geo.Point3d(12, 9, 7)
line_crv = geo.LineCurve(start_pt, end_pt)

print line_crv.PointAtStart
print line_crv.PointAt(line_crv.Domain.Min)

print line_crv.PointAtEnd
print line_crv.PointAt(line_crv.Domain.Max)

line_crv.Reverse()

print line_crv.PointAtStart
print line_crv.PointAt(line_crv.Domain.Min)

print line_crv.PointAtEnd
print line_crv.PointAt(line_crv.Domain.Max)

rc, t = line_crv.NormalizedLengthParameter(0.25)
print line_crv.PointAt(t)

rc, t = line_crv.NormalizedLengthParameter(0.5)
print line_crv.PointAt(t)

rc, t = line_crv.NormalizedLengthParameter(0.75)
print line_crv.PointAt(t)

Here is a potentially useful utility function:

# Returns a point on a curve at a normalized parameter
def GetCurvePointAtNormalizedParameter(curve, norm_t):
    if not curve:
        raise Exception("Curve is null")
    if norm_t < 0.0 or norm_t > 1.0:
        raise Exception("Parameter not normalized")
    rc, curve_t = curve.NormalizedLengthParameter(norm_t)
    return curve.PointAt(curve_t)

In looking through RhinoCommon, it looks like you can just use Curve.PointAtNormalizedLength, which does what my function (above) does.

For example:

print line_crv.PointAtNormalizedLength(0.25)
print line_crv.PointAtNormalizedLength(0.5)
print line_crv.PointAtNormalizedLength(0.75)

Sorry I didn’t see this earlier - the function name is somewhat misleading (to me)…

Thanks for your help, I’ll use .PointAtNormalizedLength() in the future.

I think in GH the situation is a bit different, because when you divide a lot of curves to draw even more curves, Curve.PointAtNormalizedLength can be your bottleneck as it keeps doing the same calculation over and over again.