This is part 4 of Scott Conover's AU 2009 class on analysing building geometry.
Curve Types
Revit uses a variety of curve types to represent curve geometry in a document. The curve types and corresponding Revit API classes include:
- Bounded line – Line
- Unbound line – Line
- Arc – Arc
- Circle – Arc
- Elliptical arc – Ellipse
- Ellipse – Ellipse
- NURBS – NurbSpline
- Hermite – HermiteSpline
Here are the definitions and some notes on each of these curve types:
- Bounded line: A line segment defined by its endpoints. Obtain endpoints from Curve.get_Endpoint().
- Unbounded line: An infinite line defined by a location and direction. Identify these with Curve.IsBound. Evaluate point and tangent vector at raw parameter zero to find the input parameters for the equation of the line.
- Arc: A bound circular arc. Begin and end at a certain angle. These angles can be obtained by the raw parameter values at each end of the arc.
- Circle: An unbound circle. Identify with Curve.IsBound. Use raw parameter for evaluation (from 0 to 2π).
- Elliptical arc: A bound elliptical segment.
- Ellipse: An unbound ellipse. Identify with Curve.IsBound. Use raw parameter for evaluation (from 0 to 2π).
- Nurbs spline: A non-uniform rational B-spline. Used for splines sketched in various Revit tools, plus imported geometry.
- Hermite spline: A spline interpolate between a set of points. Used for tools like Curve by Points and flexible ducts/pipes, plus imported geometry.
Mathematical representation
Mathematical representations of all of the Revit curve types are given in Appendix A of Scott's handout document, and we include them here as well for easy online access. This section describes the curve types encountered in Revit geometry, their properties, and their mathematical representations.
Bounded Line
Bound lines are defined by their endpoints. In the Revit API, obtain the endpoints of the line from the Curve-level get_EndPoint() method.
The equation for a point on a bound line in terms of the normalized parameter 'u' and the line endpoints is
Unbound lines
Unbound lines are handled specially in the Revit API. Most curve properties cannot be used, however, Evaluate and ComputeDerivatives can be used to obtain locations along the curve when a raw parameter is provided.
The equation for a point for an unbound line in terms of the raw parameter 'u', the line origin P and normalized direction vector V is
Arcs and Circles
Arcs and Circles are represented in the Revit API by the Arc class. They are defined in terms of their radius, center and vector normal to the plane of the arc, which are accessible in the Revit API directly from the Arc class as properties.
Circles have the IsBound property set to true. This means they can only be evaluated by using a raw parameter (range from 0 to 2π), and the equation for a point on the circle in terms of the raw parameter is
Here the assumption is made that the circle lies in the XY plane.
Arcs begin and end at a certain angle. These angles can be obtained by the raw parameter values at each end of the arc, and angular values between these values can be plugged into the same equation as above.
Ellipse and Elliptical Arcs
Ellipses and elliptical arcs segments are represented in the Revit API by the Ellipse class. Similar to arcs and circles, they are defined in a given plane in terms of their X and Y radii, center, and vector normal to the plane of the ellipse.
Full ellipses have the IsBound property set to true. Similar to circles, they can be evaluated via raw parameter values between 0 and 2π:
NurbSpline
NURBS (non-uniform rational B-splines) are used for spline segments sketched by the user as curves or portions of 3D object sketches. They are also used to represent some types of imported geometry data.
The data for the NurbSpline include:
- The control points array P, of length n + 1.
- The weights array w, also of length n + 1.
- The curve degree, whose value is equal to one less than the curve order k.
- The knot vector N, of length n + k + 1.
The parametric formula for a point on the curve is given by
The sums are over i = 0,...n, and u is limited to the interval 0 < u ≤ umax.
HermiteSpline
Hermite splines are used for curves which are interpolated between a set of control points, like Curve by Points and flexible ducts and pipes in MEP. They are also used to represent some types of imported geometry data. In the Revit API, the HermiteSpline class offers access to the arrays of points, tangent vectors and parameters through the ControlPoints, Tangents, and Parameters properties.
The equation for the curve between two nodes in a Hermite spline is
Here Pk and Pk+1 represent the points at each node, Mk and Mk+1 the tangent vectors, and uk and uk+1 the parameters at the nodes, and the basis functions are:
h10(u) = u3 - 2u2 + u
h01(u) = -2u3 + 3u2
h11(u) = u3 - u2
Curve analysis and processing
There are several Curve members which are tools suitable for use in geometric analysis. In some cases, these APIs do more than you might expect by a quick review of their names. We will discuss three of them:
- Intersect
- Project
- Tessellate
Intersect
The Intersect method allows you compare two curves to find how they differ or how they are similar. It can be used in the manner you might expect, to obtain the point or point(s) where two curves intersect one another, but it can also be used to identify:
- Collinear lines
- Overlapping lines
- Identical curves
- Totally distinct curves with no intersections
The return value identifies these different results, and the output IntersectionSetResult contains information on the intersection point(s).
Project
The Project method projects a point onto the curve and returns information about the nearest point on the curve, its parameter, and the distance from the projection point.
Tessellate
This method splits the curve into a series of linear segments, accurate within a default tolerance. For Curve.Tessellate, the tolerance is slightly larger than 1/16'. This tolerance of approximation is the tolerance used internally by Revit as adequate for display purposes.
Note that only lines may be split into output of only two tessellation points; non-linear curves will always output more than two points, even if the curve has an extremely large radius which might mathematically equate to a straight line.
In the next instalment of this series, we will look the Revit API handling of faces.
Hi,
Is there a way to change the endpoints of the curves?
I've been trying to do this and have been looking for examples, but all I can find is examples of creating new curve-based elements. I'm looking for something like set_endpoints() (I know that method doesnt exist, but is there something like it?).
Thanks!
/Erik
Posted by: Erik | March 02, 2011 at 11:45
Dear Erik,
It may seem easy to set the endpoint of a bounded line, but it is much more complex for curves in general.
Furthermore, the Revit 2011 geometry library is mainly read-only, since it only provides read access to the geometry of the Revit building model elements.
You cannot write to them directly through the geometry, since they are parametrically defined, and the geometry is only a view of them, so to speak.
So in general the answer is no, no way to change the endpoint of an existing curve, you have to create a new curve from scratch and use that instead.
Cheers, Jeremy.
Posted by: Jeremy Tammik | March 04, 2011 at 06:44
Hi Jeremy
First of all, thank you for maintaing such a great blog. You and Zach Kron have been inspring me and my students with your blogs.
In your article you mentioned NURB-Spline and Hermite Spline. I guessed that these correspond to "Spline" and "Spline through points" in Revit user interface. Is this correct?
If so, Hermite Spline as mentioned in your article depends on the tangent at each control point. But Spline Through Points in Revit does not explicitly let the user control these tangents. So please can you clarify how the tangent is managed with spline-through-points.
Thanks you very much,
Posted by: Long Nguyen | September 14, 2012 at 06:17
Dear Long Nguyen,
Thank you for your appreciation, it is a pleasure!
Zach Kron inspires and entertains me as well, very much!
The Revit API documentation states that the NurbSpline class represents a NURB spline, and the HermiteSpline class a Hermite spline, so that is not really much help.
In any case, the description above seems to match what you suggest.
Does your question refer to the user interface or the programmatic control of these objects?
Through the user interface, I have no idea whatsoever.
To control these tangents programmatically, the Hermite spline creation method NewHermiteSpline provides two overloads:
- (IList(XYZ), Boolean) creates a Hermite spline with default tangency at its endpoints.
- (IList(XYZ), Boolean, XYZ, XYZ) creates a Hermite spline with specified tangency at its endpoints.
Cheers, Jeremy.
Posted by: Jeremy Tammik | September 14, 2012 at 08:02
Thank you for your (very fast) reply Jeremy.
I actually referred to the tangent in the user interface, not in the API.
One question I have heard so many people asked is how to smoothly join two spline-through-points in Revit. I know that in order to do this, we must make sure that the tangents of the two spline-through-points where they meet line up perfectly. Sadly I cannot see how to achieve this since spline-through-points in the revit user interface does not explicitly let the user control the tangents. I know that the other type of spline in the user interface (the NURBS one) does expose the tangents to the user. However, since the control points of these NURB-Spline cannot be attached to reference points, the NURB-Spline are pretty much useless in parametric design where we want to use the parameters to control the shape of the curve.
Probably I will try to look into the API to see if I can create a new class of Hermite Spline that expose the tangents in the user interface.
Posted by: Long Nguyen | September 15, 2012 at 12:28
Hi Kean,
How to determine the Curve center between two Curves
corresponding bellow?
Arc – Arc
Circle – Arc
Elliptical arc – Ellipse
Ellipse – Ellipse
NURBS – NurbSpline
Hermite – HermiteSpline
Could you help me?
Thank and Regards,
Posted by: Bang | June 26, 2013 at 00:30
Hi Bang,
Is this question for Jeremy or for me? :-)
Regards,
Kean
Posted by: Kean Walmsley | June 26, 2013 at 09:08
Dear Bang,
That is a nice geometrical question you have.
The Revit Geometry API does not provide direct support for that functionality, so you would have to implement it yourself, for instance by querying the two original curves for their underlying parametric definition data, calculating the input data for the curve between the two (complex!), and feeding that into the Revit API again to generate it, e.g.
http://www.coe.org/p/fo/et/thread=18887
Cheers, Jeremy.
Posted by: Jeremy Tammik | June 27, 2013 at 07:54
Hi Jeremy,
http://www.coe.org/p/fo/et/thread=18887
I read it and I'll try, if you have code a specific example in Revit API with NurbSpline, HermiteSpline... I hope you share with me!
Thank and Regards,
Posted by: Bang | June 28, 2013 at 23:21
Dear Bang,
Thank you for the interesting pointer.
It would be quite easy to implement in Revit, actually, making use of the generic parametrised curve functionality.
Just determine the two curve parameter ranges, [begin(1),end[1)] and [begin[2], end(2)]. Iterate over the two ranges simultaneously, generating points p(1,i) and p(2,i), calculate the midpaoints between them, and connect the dots.
Cheers, Jeremy.
Posted by: Jeremy Tammik | August 13, 2013 at 09:32
Dear Bang,
I went and implemented my suggestion:
http://thebuildingcoder.typepad.com/blog/2013/08/generating-a-midcurve-between-two-curve-elements.html
I hope you like it.
Cheers, Jeremy.
Posted by: Jeremy Tammik | August 15, 2013 at 09:15
Hello Jeremy,
I have List of points through which I want to create curve so that I can create family instance.Actually in GSA analysis software there is explicit member which is made of number of elements.Currently I am importing elements of member one by one and so these are separate instance in Revit.If I can create curve through list of points and I will be in situation to create single instance in Revit.Can you please advice me something on this?
Posted by: sandee kumar | September 10, 2013 at 01:43
Dear Sandeep,
It is hard for me to say anything, because you leave so many aspects open.
Especially since it sounds to me as if you are creating the family yourself on the fly.
That leaves you free to implement it in any way you see fit.
Sounds like fun.
Good luck!
Cheers, Jeremy.
Posted by: Jeremy Tammik | September 10, 2013 at 09:07
Hi Jeremy!
could you tell, please, is it possible to create closed spline using Revit API.
Theoretically it is possible to do using next method:
NurbSpline Create(
IList controlPoints,
IList weights,
IList knots,
int degree,
bool closed,
bool rational)
This method has parameter closed, but when I try to create spline with points:
p1 = new XYZ(28, 4, 0.07);
p2 = (new XYZ(28, 4, 0.11);
p3 = (new XYZ(29, 4, 0.09);
p4 = (new XYZ(30, 4, 0.07);
p5 = (new XYZ(29, 4, 0.05);
p6 = (new XYZ(28, 4, 0.03);
p7 = (new XYZ(28, 4, 0.07);
Knots are next:
-0.333333; 0; 0; 0; 0.333333; 0.333333; 0.666667; 0.666667; 1.0; 1.0; 1.0;
Curve degree = 3, points are 7,
so knots count = 3 + 7 + 1 = 11.
But I'm getting error:
"The size of knots must equal the sum of degree, the size of the controlPoints array and 1. The first degree+1 knots should be identical, as should the last degree+1 knots. The knots in the middle of the sequence must be non-decreasing."
If I create spline with only part of points (from p1 to p4 ) I'm getting correct result.
Does API has some special rule for closed splines?
Thank you,
Olga
Posted by: Olga | October 20, 2014 at 06:51
Dear Olga,
Sorry this is taking so long. I am discussing the issue with the development team. Please hold on.
Cheers, Jeremy.
Posted by: Jeremy Tammik | October 31, 2014 at 02:41
Dear Olga,
I heard back from the development team. They say:
We talked it over and couldn't find a valid use of closed NURBS curves in Revit proper.
The field is present, but never used. In fact, it would have been better not to expose it to the API in its current state.
We introduced the method NurbSpline.Create(controlPnts, weights) without the extra options because the rest of the parameters are never really varied in the Revit implementation.
That being said, the error reported is explaining what the method expects, specifically:
“The first degree+1 knots should be identical, as should the last degree+1 knots”
In general, the specified knot sequence doesn't make sense to us.
Assuming our closed splines are defined in the same way as open ones, we'd expect something like 0,0,0, [five evenly spaced numbers between 0 and 1], 1, 1, 1.
I hope this clarifies.
Cheers, Jeremy.
Posted by: Jeremy Tammik | October 31, 2014 at 09:10
Thank you very much, Jeremy!
It's clear now.
Best regards,
Olga
Posted by: Olga | November 06, 2014 at 07:48