Python - Getting the normal of a line


I’m trying to create some Curves (lines) by offsetting existing ones.

I see that in the Curve class there is a method for creating an Offset one: Curve.CreateOffset Method.

To do this, you need to specify the original curve, the offset distance and the normal.

The API help states that the normal is ‘The normal of the plane defining the offset direction.’

I assume that the normal is something which I’ll need to extract from the original line, but I cannot see any Property in the Line or Curve class which hold the Normal.

Or maybe I need to create the normal from the original lines start and end points?

I’d appreciate some advise?


Keep in mind that lines are 1D objects. That means that they can lie on many planes and thus it’s impossible to define their normal. Arcs and circles on the other hand do have a normal because they can lie only in a single plane.

In the context of the API, the normal refers to a direction vector. The equivalent in dynamo is the translate node.That vector can be anywhere in the euclidean space and we only care about its direction.

I see, so if I need to specify ‘The normal of the plane defining the offset direction.’ as required for the Offset then it can only come from the Start and End points I guess?

The API help states that its looking for Autodesk.Revit.DB.XYZ for the normal - an XYZ is just a point isn’t it? and not a direction vector?

XYZs are both points and vectors :slight_smile: Think of them as a vector that starts at the origin and ends at the XYZ coordinates.Have you seen the primer? It has a lot of examples on this:

1 Like

mmm, OK. Still struggling to understand this.

Surely a XYZ is a point not a vector, a vector requires a direction?

From Primer: There is a key difference though: Points describe a position in a given coordinate system while Vectors describe a relative difference in position which is the same as saying “direction.”

But your saying that Revit work out a vector from the origin to the XYZ coordinates that I’ll specify? I don’t see how this would relate to my line though?

I assume this is required to work out what side to Offset the line to… Maybe I’m miss understanding why a vector is required for the Offset?


The reason they want a Vector for this case is because a Vector has Direction and Magnitude (Length) which in this case would be the direction in which you want to offset the curve in, and by how much you want to offset it. The reason one can express (represent) a vector as a XYZ coordinate is because typically in Cartesian coordinates vectors are considered to be always originated at 0,0,0 so the Direction/Magnitude can be calculted from 0,0,0 to X,Y,Z that you defined. The easiest way to imagine a Vector is by two points. Origin and Target and represent it with a Line. That’s how I always think of them. Hope this helps.

1 Like

Will attempt to explain with an analogy …

Say you want to offset a line by a distance R

Now, Imagine the line to be the axis of a cylinder (of radius R)
All lines parallel to the axis drawn on the surface of the cylinder, have effectively been offset by R
This could me any number of lines.(a minimum of 360 assuming 1 line per degree)
So, you aren’t being specific enough by just specifying the offset distance. You’ll need to specify the direction.

The base profile of the cylinder is a circle, the center of which is the start/end point of the axis.
Imagine the vector / direction / normal to be a line joining the center point to the start/end point of the desired line drawn on the surface.

Hope I’ve made sense :slight_smile:

1 Like

Kevin I am no dynamo expert, but perhaps I can answer your question because I think I see the confusion you are having. The origin is relative to the object being moved so if you have a point on the screen, and you want it to move 2 units to the left, that would be an x of -2, or a vector of -2, 0. 0 In which case you can as Konrad is calling it draw a line from the origin to the destination, in a direction, (left) which would be your vector. If you wanted to move the object up 4 units (vertically) from the reference plane it would be a vector of 0,0, 4. If you wanted it to move, “up and away” now you would have something like 2, 3, 4. This type of vector can only work with a single point because there is no need to physically orient the object, because it is just a single point in space and there is no front, right, back, top, or bottom. In a 3D object, however there is. So if you want to move the 3D object you have to first define a normal plane. This mean you have to define where you are starting from like choosing your work plane in revit when you are drawing in 3D. Like ok you want to draw an extrusion? You have to first define what the work plane is and then the extrusion will be “normal” to the work plane. So think of it like that. if you have your work plane defined as the reference plane and draw a 1’-0" extrusion, your are drawing (essentially) a 3D vector in the Z axis or 0,0,1 if you set your work plane as the right/left plane and draw a 1’-0" extrusion, you are essendtially drawing a vector to the left or right of 1’ depending on how you define the extrusion, or -1,0,0 or 1,0,0. does that make sense? What Konrad is not telling you is that when you get more complicated is that Cartesian vectors are added end to end, and only at 90 degree angles to get your object to appear at the resultant location. First you have to start at the starting point only make 90 degree turns (3 of them in Cartesian coordinates to get to any point in space) but first you have to align your self, “normal” to the plane in the direction you want to go in the first place. For example if you want to get to point 1,3,5 you might first align yourself "Normal to the Y plane, which would allow you to travel 1 unit in the x axis, then you would align yourself normal to the X plane and travel 3 units in the y direction, and then you would align yourself to the XY plane and travel 5 units in the Z direction, ending you at point 1, 3, 5. That is how programing works when you are starting at some random point in space you have to tell it where you are starting from to tell it how to move. Using the same example from before you can get to the same point by first traveling in the Z direction, then X, then Y resulting in the same point. Therefore you have to tell it how its going to move by choosing the right Normal plane so that it knows where its going to move first and in which direction. You have to point in in the right direction first. Essentially by “Putting it Normal to a plane of your choosing” then telling it how far to go. In Dynamo you can do that in one step, (one vector) but first you need to define the normal plane of which it is going to move, and then how far. What Konrad meant (i think) is the origin of how you define your object in space and its end location which results in a resultant vector. but you have to first know how resultant vectors are calculated in the first place before that would make sense, and is assuming you knew that. Simply put, a “normal” is a line that intesects a plane at a 90 degree angle. If a line is 90 degrees to a plane (perpendicular) it is considered “Normal” to that plane. Similarly from the planes perspective a line which is 90 degrees to it would be considered its “Normal”. Also, please note that every plane has 2 Normals, one the comes out the top and one that comes out the bottom. So you have to tell it which one (which direction ==vector) you are using. If this helps please give show me some love by hitting the heart down below because Im new here. Hope that helped!


Thanks for your response chaps!

Ok, so I understand that the normal is effectively defines the plane for the offset based on the origin (I think I was getting confused with the fact that I’m working with a detail line which I assumed was 2D).

I put together this as a sample example to try to understand the use of the normal in an offset:

With the script being:

Offset Room Boundary.dyn (44.8 KB)

This offsets the line based on the sliders, I get that whilst its a detail line, its still offsetting in 3D space based on the normal plane, as per the graphic in Dimitar’s post above.

But if I wanted to offset the original line by, say, 100" to the left would it not be a case of setting:

Distance to 100
X Normal to 0
Y Normal to 0
Z Normal to any value.

But that doesn’t work.

I think the problem is that I cannot work out the ‘left’ or ‘right’ side of the line if the Normal is based on a vector between the origin and the point I specify?

OK, I think I’ve worked out whats been confusing me.

A normal of X=0. Y=0, Z=1 will produce an offset as expected, it was the distance that didn’t seem to work out.

The reason is that I’ve forgotten that Revit internally works in feet, (I work in Metres) so, if I convert then it offsets as expected…

Glad that’s sorted now!