Creating a Curved Beam

Here is a solution from my colleague Joe Ye on how to create a curved beam.
This is also the first and so far only Building Coder sample that demonstrates the use of the Revit API DoubleArray and NurbSpline classes.

Question:
I am creating curved beams using

NURBS
.
When the spline in parallel to the XY plane, all works well:

Curved beam in XY plane

When the curve is lying in the YZ or XZ plane, however, the resulting beam is straight:

Curved beam remains straight

How can I create the correct curved beam in all orientations?

Answer:
This was actually a known issue in Revit 2009, and has been fixed in Revit 2010.
I tested creating a nurbs-defined curved beam in the XZ plane in 2010 and it works well.
Here is the resulting shape in front view:

Curved beam is curved

This is the code of the Execute method used to create this beam, using a set of points in the XZ plane:


Application app = commandData.Application;
Document doc = app.ActiveDocument;
 
Level level = doc.ActiveView.Level;
 
FamilySymbol symbol = null;
 
string path = "C:/Documents and Settings"
  + "/All Users/Application Data/Autodesk"
  + "/RST 2009/Metric Library/Structural"
  + "/Framing/Steel/";
 
string family = "M_WWF-Welded Wide Flange";
 
string ext = ".rfa";
 
string filename = path + family + ext;
 
string symbolName = "WWF600x460";
 
if ( doc.LoadFamilySymbol( filename, symbolName, out symbol ) )
{
  Curve c = CreateNurbSpline( app );
 
  FamilyInstance inst
    = doc.Create.NewFamilyInstance(
      c, symbol, level, StructuralType.Beam );
 
  return IExternalCommand.Result.Succeeded;
}
else
{
  message = "Couldn't load " + filename;
  return IExternalCommand.Result.Failed;
}

The important step is the call to the CreateNurbSpline method, which generates the required input curve from a set of hard-coded points.
Here is the definition of that method:


NurbSpline CreateNurbSpline( Application app )
{
  XYZArray ctrPoints = app.Create.NewXYZArray();
 
  XYZ xyz1 = new XYZ( -41.8 * 1, 0, -9.02 * 1 );
  XYZ xyz2 = new XYZ( -9.2 * 2, 0, 0.82 * 50 );
  XYZ xyz3 = new XYZ( 9.2 * 2, 0, -0.82 * 50 );
  XYZ xyz4 = new XYZ( 41.8 * 1, 0, 9.02 * 1 );
 
  ctrPoints.Append( xyz1 );
  ctrPoints.Append( xyz2 );
  ctrPoints.Append( xyz3 );
  ctrPoints.Append( xyz4 );
 
  DoubleArray weights = new DoubleArray();
 
  double w1 = 1, w2 = 1, w3 = 1, w4 = 1;
 
  weights.Append( ref w1 );
  weights.Append( ref w2 );
  weights.Append( ref w3 );
  weights.Append( ref w4 );
 
  DoubleArray knots = new DoubleArray();
 
  double k0 = 0, k1 = 0, k2 = 0, k3 = 0,
    k4 = 34.425128, k5 = 34.425128,
    k6 = 34.425128, k7 = 34.425128;
 
  knots.Append( ref k0 );
  knots.Append( ref k1 );
  knots.Append( ref k2 );
  knots.Append( ref k3 );
  knots.Append( ref k4 );
  knots.Append( ref k5 );
  knots.Append( ref k6 );
  knots.Append( ref k7 );
 
  NurbSpline detailNurbSpline
    = app.Create.NewNurbSpline(
    ctrPoints, weights, knots, 3, false, true );
 
  return detailNurbSpline;
}

Many thanks to Joe for providing this solution!


Comments

13 responses to “Creating a Curved Beam”

  1. Hi jeremy,
    I’ve got a problem with CurrentViewSheetSet
    I’ve got a simple code with a ComboBox wich contains SheetSets
    When I choose one in my list, I use the PrinterManager.ViewSheetSetting.CurrentViewSheetSet = my viewSheetSet choosen in my combo.
    But the method : PrinterManager.ViewSheetSetting.CurrentViewSheetSet.Views never return me the currentViews of the ViewSet selected….
    Have you ever try this?
    Do you want my code?

  2. Pierre,
    try
    ViewSheetSet viewSheetSet = PrinterManager.ViewSheetSetting.CurrentViewSheetSet;
    viewSheetSet.Views = myViewSheetSet.Views;
    PrinterManager.ViewSheetSetting.Save();
    I think the way to do it is to get the current view sheet setting, and then set the views of that setting to be the ones of the viewSheetSet that you selected.
    Let me know how you go, if needed, post a full thread on AUGI and I’ll try to help you out (or jeremy can if he likes!) – I’ve dont a fair bit of API work with printing, and have come across many problems along the way.

  3. I’m gonna try Rod.
    Thx for your advice.
    I’ll keep you inform about my problem.
    Cheers!

  4. Jake Haggmark Avatar
    Jake Haggmark

    Hi I’m creating a single curved beam/joist. Will I have to use this NURB stuff that I don’t understand or is there a simpler way?

  5. Dear Jake,
    That obviously depends on the complexity of the curve you require. If it is very wiggly, you will probably need to use a NURB to represent it anyway. If it is just a simple circular or elliptical arc, you can implement a geometric utility function to create a NURB to represent the simpler geometrical curve.
    I googled for “circular nurb” and found lots of hits. The first is the NURBCircleArc Tool provided as part of the Ayam package, which is a free 3D modelling environment:
    http://ayam.sourceforge.net/docs/ayam-5.html
    Here is another:
    http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261542
    A slightly more complex problem involving multiple connected circular arc segments is discussed in a mathematical paper on Composing Circular Arcs with Minimal NURBS:
    http://www.m-hikari.com/imf-password2009/5-8-2009/sommerIMF5-8-2009.pdf
    Finally, here is what you really need, a basic introduction to NURBS including a detailed explanation of how to use NURB curves to create conic sections such as circles and ellipses:
    http://www.mactech.com/articles/develop/issue_25/schneider.html
    If you do end up implementing a method to create a NURB curve representing a circular arc, please send it by for sharing with others. Thank you!
    Cheers, Jeremy.

  6. Hi again Jake,
    Did I hear you gasp slightly there, a short sharp intake of breath? Sorry for scaring you!
    In my enthusiasm over the NURBS I forgot to mention that if you just need an arc or an ellipse, you can also just use some of the simpler Autodesk.Revit.Creation.Application class curve creation methods:
    – NewArc to create an arced curve.
    – NewEllipse to create an elliptical curve.
    – NewHermiteSpline to create a hermite spline curve.
    And obviously you also have NewLine and NewLineBound to create bounded or unbounded lines, which are also curves, even though they are straight.
    The NewFamilyInstance method above just needs to be fed with a Curve object, and it can be any one of the classes derived from the Curve class, not necessarily a NURB curve.
    Cheers, Jeremy.

  7. Jake Haggmark Avatar
    Jake Haggmark

    Thanks for all the information, I’m going to dive into it now and see what I can do.

  8. how to use this code for generating curved beam in revit…??
    pls explain bcoz i’m new to coding and stuff…

  9. Dear Adamya,
    Simply plug the code presented above into a Revit add-in.
    If you are new to coding and the Revit API, I would suggest you learn the basics before attempting to create a curved beam, e.g. look at the Getting Started category of this blog and first of all the DevTV introduction:
    http://thebuildingcoder.typepad.com/blog/2009/12/updated-devtv-introduction-to-revit-programming.html
    Cheers, Jeremy.

  10. John Castro Avatar
    John Castro

    Hey Jeremy, I’m trying to create a beam that curves in both plan and elevation. In Revit 2012, I’m trying to create the beam by 3D snapping a spline to columns, however the beam ends up straight even though the spline is snapped to the columns. Do you think this method will work if I hard-coded the XYZ coordinates of the columns? I’m new to the Revit API and before I dig into it, just wanted some reassurance that it’s not a waste of time.
    Thanks, John

  11. Dear John,
    Sorry, I simply don’t know. I would have to try it out, same as you.
    Cheers, Jeremy.

  12. Jeroen Janssen Avatar
    Jeroen Janssen

    Dear Jeremy,
    First of all, many thanks for your vast amount of inspiration and help you’re providing here on the forum.
    Currently I’m working on a conversion tool directly from Rhino to Revit, through the API. I want to convert NURBS curves from Rhino, so I believe this method to create the nurbspline seems like the best way to go.
    Eventually I want to loft a number of curves, but I need references for that. Now that brings me to the problem right away. I can’t seem to get a reference property from the NewNurbSpline method, it results in a null value.
    Do you have any ideas where I might have to look for an answer?
    Does it possibly has to do with adding a new transaction or regenerating the model?
    Or is it because I’m opening a new familydoc in the function and the Application is coming from outside of the function?
    Here’s a little snap of my code (it’s in VB, but a C# answer is fine as well ;)), I can send you more if that needs more clarification.
    Many thanks,
    Jeroen Janssen
    Public Function CreateSurfaceMassFamilyTool(ByVal strL As List(Of String()), ByRef UIapp As UIApplication, ByRef app As Application) As Boolean

    Dim ref_ar As New ReferenceArray
    Dim startVal As Int32 = 5
    Dim ptList As New List(Of XYZ)
    Dim wL, kL As New DoubleArray()
    Dim counter As Int32 = 0
    For j As Int32 = startVal To s.Length – 1 Step 2
    Dim ptVal As String() = s(j).Split(“;”)
    Dim X As Double = mmToFoot(ptVal(0))
    Dim Y As Double = mmToFoot(ptVal(1))
    Dim Z As Double = mmToFoot(ptVal(2))
    Dim ptA As New XYZ(X, Y, Z)
    ptList.Add(ptA)
    wL.Append(1)
    kL.Append(counter)
    counter += 1
    Next
    Dim nurbs As NurbSpline = app.Create.NewNurbSpline(ptList, wL, kL, 1, False, False)
    ref_ar.Append(nurbs.Reference)
    End Function

Leave a Reply to Rod HowarthCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading