Going back to understanding geometry again, I feel like I’m too late for this. But can anyone explain or suggest a reading/link to understand how normals are treated for curves, especially lines? In the case of surfaces, you have a plane, and perpendicular to that is the normal. The same can be said with some planer curved like polygons, ellipses, parabolas, or even a sine curve. But it feels counterintuitive to me how the plane of a line (or point) is determined. It could be existing in (or parallel to) an infinite number of planes.

Please consider this small crude visualization.

In Blue: Curve.NormalAtParameter
In Black: Curve.Normal
In Orange: Lines to which normals are calculated
For Curve.NormalAtParameter the center point of Orange lines is the origin/start point and for Curve.Normal the outward endpoint is the starting point.

Normals for lines/points on XY plane are perpendicular to the XY plane. But for the other plane (say PQ) rotated at 45 degree with respect to Y axis, the normals are seemingly randomly pointing away and not perpendicular to the plane PQ in the same way.

My basic understanding is at a curves start point, the normal is the X axis of the framed plane at that point (each point is also like a plane due to its orientation/origin as point). Effectively if you look forward, the X plane would be to your right. This is why line draw direction will reverse the normal direction.

As you travel along an interpolated curve between points (straight, arc, spline etc.), this plane reference would also rotate to match how far between the interpolation points you are.

So if you take a point, move it away and rotate it you would expect the normal to rotate along the domain of a curve’s domain between those points as well. I’m not 100% sure if thats how it works in all engines though, I know some will assume their frame orientation based on their relationship to the start point.

I’ll do some tests and come back on this one as this is generally my assumption in most cases.

Thanks. I’m not sure if I understand it all though.

If I try to find the Normal at Parameter 0 (start point i.e. origin) for these lines, the resultant vectors are parallel and overlapping the very lines?

In testing in both dynamo and grasshopper it seems to depend on the type of method that generates the curve. For lines, it generally keeps the normal orientated to the original point that the line begins from (even if the end point is rotated in its facing plane). For interpolated curves like splines it seems that the normal is a bit arbitrary, and depends on the two segments it is related to, or the two that come after it if it’s start or end.

I’m keen to hear the deeper rationale as well but I expect a lot of this depends on the way the geometry engine has been set up to interpret the rotation and generation methods behind the line/curve.

I observed the below things in my case. Curve.NormalAtParameter (blue) is perpendicular to the curve and also to the Z axis i.e. it always exists on the XY plane. The orientation of the normal is clockwise to the curve (if the curve is considered a vector, start point to end point).

Curve.Normal (black) is perpendicular to the curve and also to the X axis.

This is entirely accurate. The exact math and reasoning as to ‘why’ the normals rotate requires a VERY deep dive into the geometry library (not the stuff Dynamo uses but the libraries which Dynamo utilizes) and is well beyond my skill set.

I do know that in the case of radial lines, after you cross the 180 degree threshold the normals ‘reverse’. Similar results happen if you draw a waving spline along the X axis and pull the coordinate system. You get coordinate systems inverting 180 degrees in sharp distances when you go from a Y+ curve to a Y- curve. Civil 3D goes to great lengths to ensure this doesn’t happen with it’s curves (which I expect is part of the reason it requires special nodes for pulling alignment curve geometry into Dynamo).

When in doubt I find it best to always pull the coordinate systems along the curve as you go, and/or to force behavior by changing the geometry type (ie: PolyCurve instead of a line). There are also some nodes coming in a future build (Curve.OffsetMany) which allow dictating the normal, which will help ensure consistency.