Creating a Wall with a Sloped Profile

Here is a

question from Winnie

on the creation of walls with a sloped profile:

Question:
I’m having problems trying to create walls that have constant sloped top edge.
I tried using the NewWall method and passed in a CurveArray that contains the edges of the wall that would create a sloped top but the result was still a rectangular wall.
Also, how would you alter an existing wall to have a top sloped edge?

Answer:
Using NewWall and supplying a profile to define the slope is exactly the right approach.
I implemented a minimal new command named CmdSlopedWall to do this.
Here is the code for the Execute method to create a wall with a sloped upper edge:


Application app = commandData.Application;
 
Autodesk.Revit.Creation.Application ac
  = app.Create;
 
CurveArray profile = ac.NewCurveArray();
 
double length = 10;
double heightStart = 5;
double heightEnd = 8;
 
XYZ p = ac.NewXYZ( 0.0, 0.0, 0.0 );
XYZ q = ac.NewXYZ( length, 0.0, 0.0 );
 
profile.Append( ac.NewLineBound( p, q ) );
 
p.X = q.X;
q.Z = heightEnd;
 
profile.Append( ac.NewLineBound( p, q ) );
 
p.Z = q.Z;
q.X = 0.0;
q.Z = heightStart;
 
profile.Append( ac.NewLineBound( p, q ) );
 
p.X = q.X;
p.Z = q.Z;
q.Z = 0.0;
 
profile.Append( ac.NewLineBound( p, q ) );
 
Document doc = app.ActiveDocument;
 
Wall wall = doc.Create.NewWall( profile,
  false );
 
return CmdResult.Succeeded;

This is what the resulting wall looks like:

Wall with a sloped profile

Regarding your second query on the modification of an existing wall:
applying a profile to an existing wall which has none to start with is currently not supported by the API.
Such a method would be similar to the Truss SetProfile method, but walls do not currently support this.

Here is
version 1.0.0.22
of the complete Visual Studio solution with this new command implementation.


Comments

31 responses to “Creating a Wall with a Sloped Profile”

  1. Hey Jeremy,
    I tried it out and it works but I had to use
    “doc.Create.NewWall( profile, true );”
    instead of
    “doc.Create.NewWall( profile, false );”
    before the wall appeared. Maybe I have the view options set to not show non-structural items. I’m working with Revit Structure by the way.
    Thanks so much for the lightning fast response! I was working on something else after I sent you that question so I didnt have the time to try this out until now. Your response was awesome!

  2. Hi Winnie,
    I’m very glad to hear it worked so well, and thank you very much for the appreciation!
    Cheers, Jeremy.

  3. Malcolm Carvalho Avatar
    Malcolm Carvalho

    How do I create a wall with a given thickness? I have been able to set the length and height of the wall before creating it, but am clueless about setting the wall width. Can you help?

  4. Dear Malcolm,
    The thickness of a wall is determined by its type. To change between different thicknesses, you need to switch wall type using the Wall.WallType property. To define a type with a new wall thickness, you can duplicate and modify an existing type. This is demonstrated in
    http://thebuildingcoder.typepad.com/blog/2008/11/creating-a-new-family-symbol.html
    Creating new types for other categories is also discussed in
    http://thebuildingcoder.typepad.com/blog/2009/02/inserting-a-column.html
    http://thebuildingcoder.typepad.com/blog/2009/02/inserting-a-beam.html
    I hope this helps.
    Cheers, Jeremy.

  5. vishal Avatar
    vishal

    Hi Jeremy,
    I am searching around for a simple thing that how to add a new layer in wall using Revit API? Here idea is to create wall with multiple layers and assigning thickness to each of the layer.
    i have tried Append and Insert options but failed to do so.
    Will be much much thankful if you can guide me.
    waiting for your reply.
    -Bye

  6. Malcolm Carvalho Avatar
    Malcolm Carvalho

    Thanks Jeremy.
    Now I need to create a custom wall type , where I can add layers, and also change the attributes of the layers (thickness, material). Do let me know how this can be done.

  7. Dear Vishal and Malcolm,
    Thank you for your two queries. You are both asking how to add new layers to a compound wall structure.
    I looked into this issue and note that the CompoundStructureLayerArray class does indeed provide methods to append and insert new layers, which is what you would need to do. However, I see no way to create a new layer yet, i.e. a CompoundStructureLayer instance. I am looking into this further and will add more info as soon as I find out something.
    Vishal, when you say that you tried the Append and Insert methods, where did you obtain the layer from to pass in to them?
    Malcolm, to change attributes of existing layers should not be hard. The two following posts show how you can access the compound layer structure of the wall, and once you have that, you should be able to modify all the writeable properties of each layer:
    http://thebuildingcoder.typepad.com/blog/2008/11/wall-compound-layers.html
    http://thebuildingcoder.typepad.com/blog/2009/02/compound-wall-layer-volumes.html
    Creating a new wall type is explained in
    http://thebuildingcoder.typepad.com/blog/2008/11/creating-a-new-family-symbol.html
    Cheers, Jeremy.

  8. Vishal Avatar
    Vishal

    Thanks Jeremy.
    This is the code I have used to append a layer to the wall type.
    IEnumerator wallTypeEnum = currentDoc.WallTypes.GetEnumerator();
    wallTypeEnum.Reset();
    wallTypeEnum.MoveNext();
    WallType type1 = wallTypeEnum.Current as WallType;
    WallType newWallType = type1.Duplicate(“MyType”) as WallType;
    wallTypeEnum.MoveNext();
    type1 = wallTypeEnum.Current as WallType;
    CompoundStructureLayer layer = type1.CompoundStructure.Layers.get_Item(0);
    //I get an exception saying “Collection is read-only” when I call Append
    newWallType.CompoundStructure.Layers.Append(layer);
    //even insert fails
    //newWallType.CompoundStructure.Layers.Append(layer,newWallType.CompoundStructure.Layers.Size);
    Can you let me know what should be done?
    Regards,
    Vishal

  9. Dear Vishal,
    Thank you for the sample code and yes, I can tell you exactly what to do:
    1. Wait, and
    2. Don’t hold your breath.
    Sorry for the bad news, but I tested some similar code and received similar results, and that is the current state of affairs. There is currently no way to create a valid CompoundStructureLayer instance through the API, and the CompoundStructureLayerArray instance is in fact read-only, in spite of providing the two methods Append and Insert to append and insert new layers.
    Sorry, there is currently no way to do this.
    The development team is aware of the wish to create a new CompoundStructureLayer and make the CompoundStructureLayerArray writeable, but I cannot say when that functionality will become available.
    A work-around would be to create the required number of layers manually and save the wall types in the template file. Then, when your application needs a new wall type with a specific number of layers, it can use a suitable one of the manually created predefined wall types and duplicate and modify that.
    Cheers, Jeremy.

  10. vishal Avatar
    vishal

    Much thanks Jeremy for your reply.
    One question i would like to ask here is which will be better option,
    1.Creating customized library files (.rfa) 2.Creating Template file (.rte){As you have mentioned}.
    Also It will be great help if i can get any reference document on this topics.Sample code will be much appreciated……
    Waiting for your reply.
    -Bye,TC.

  11. Dear Vishal or TC,
    I am no expert on the optimal Revit product implementation, usage, or content generation, so I cannot give you any well-founded advice on those two options, I’m afraid.
    We are currently working at gathering experience and preparing training material to demonstrate the use of the new family API, so there will be some news in that area in the near future.
    Cheers, Jeremy.

  12. Jeremy,
    Thanks for your informative blog.
    I’ve been trying a few ways to create walls that have faces that are tapered, not just profile edges as shown in this example. As you probably know, your example will not work if you specify differing Y values for the profile curves (at least I haven’t been successful). Is there currently a way to do this in the API? So far in my examination of the API, the best I can hope for is to create a geometric Form with tapered faces (using the API) and then in Revit (not the API) use the massing tools to create a wall from a mass face.
    Do you have any thoughts or suggestions on this matter?
    Thanks for your time,
    Deric

  13. Dear Deric,
    Thank you for your appreciation and your interesting query. Tapered which way, I wonder? Do you mean that the wall profile in plan view is tapered, or the wall cross section, i.e. in a section view perpendicular to the wall location line?
    Next question: can you create the kind of wall you require through the user interface? If not, it almost certainly cannot be done through the API either. If so, could you please briefly describe how? Thank you!
    I saw a case about creating a stone wall that tapers as it ascends, i.e. reduces in thickness. To create such a battered wall through the user interface, one can use the in-place family tools and make an extrusion or sweep. In another case, I saw mention of using the vertical compound wall system, and specifically top and bottom extensions.
    In Revit 2010, we have the new family API which offers a lot of possibilities for standard families, but unfortunately it does not cover in-place families, nor system ones such as walls.
    Cheers, Jeremy.

  14. Hi Jeremy,
    Thank you for your response. My apologies if I wasn’t clear regarding the taper direction. I am referring to a taper in cross section. Here is a link to a simple example of what I am trying to achieve:
    http://www.dericwallace.com/tapered_wall.jpg
    The way that it is done through the user interface is to first create a mass that has a taper in cross section. Then, using the Wall By Face command in the Massing tools, I select the desired wall type in the selector, then I click on the tapered face.
    I have examined the possiblity of creating a wall via the API and getting the top edge and moving it in the XY plane but the method “MoveSubElement” only applies to Form objects. This leads me to believe that I will not be able to fully achieve what I would like using the API only. Instead I would have to use the API to create these tapered masses then apply a wall to a face using the user interface.
    I think using an in-place wall family for this is not desirable as I would not be able to get the wall layers as you can see in the above link. As you have said, in-place families are not covered in the API.
    Thanks again,
    Deric

  15. Dear Deric,
    Thank you for the sample image, it helps a lot to explain. I would actually not call that wall tapered at all, but slanted. For me, tapered means that its thickness changes, but as far as I can see you only mean the wall is at an angle instead of being vertical. I am checking with my colleagues about this and will get back to you when I have some news.
    Cheers, Jeremy.

  16. Dear Deric,
    I had a chat with my colleagues, and we are pretty sure that this cannot be done through the API in 2010.
    Your two-step approach generating a mass through the API and a wall in the UI seem the closest one we can currently achieve via API.
    The good news is that functionality is in place to achieve this in a future release.
    Cheers, Jeremy.

  17. Deric Avatar
    Deric

    Thanks Jeremy.
    Sorry about the taper confusion. I guess I was referring to the original mass that I had used to generate the wall.
    Thanks for your help. I really appreciate it.
    Deric

  18. Hi Jeremy,
    Your blog is better than the Developer’s Guide haha. I saw this post and I have a doubt about this topic, How can I get the profile of a wall or a floor? (Location Property is only a single curve).
    Regards,
    Salvador

  19. Dear Ivan,
    Thank you for the nice compliment :-)
    Access to the detailed internal structure of layered walls is described in
    http://thebuildingcoder.typepad.com/blog/2008/11/wall-compound-layers.html
    and
    http://thebuildingcoder.typepad.com/blog/2009/02/compound-wall-layer-volumes.html
    Cheers, Jeremy.

  20. Hi Jeremy,
    I am struggling to figure out how to set a wall’s “Location Line” to “Finish Face: Interior” in code prior to drawing the wall. I would like the interior face of the wall to be at the coordinate points I supply instead of the default “wall Centerline”. Do you happen to have any example code along these lines just sitting around waiting to be posted?
    Thanks in advance
    Mike

  21. Dear Mike,
    You can explore this as follows:
    Create a new wall and look at its parameters, e.g. using the Revit API Introduction labs built-in parameter checker. One of the parameters is
    WALL_KEY_REF_PARAM ‘Location Line’ Integer read-write
    It has an initial value of zero. Looking at the wall properties in the UI, I see that the location line property is set to centre line. If I change the property to ‘Finish Face: Interior’ through the UI and then look at the parameter again, its value has now changed to 3.
    You should be able to invert this process, i.e. set the built-in parameter WALL_KEY_REF_PARAM to have a value of 3 through the API, and that should correspond to ‘Finish Face: Interior’.
    Cheers, Jeremy.

  22. Thanks Jeremy,
    Perhaps I can coax you into providing an answer to another problem I am having. I want to use the “NewSweep” method to create a 3D curb line that follows along a path of 3D points. The NewSweep method can be invoked in two ways, one uses a ReferenceArray and the second uses a CurveArray. There is an example provided in the VSTAFamily Sample code that illustrates the CurveArray version and I have used that code to layout an entire curbline without issues. Unfortunately, I need to use the first version that allows for a sweep to follow a 3D path using the ReferenceArray version. I keep getting an error saying the object is not referenced, and I am clueless as to why.

    I am using VB.NET and here is the code I modified from the sample code:

    Dim arrarr As CurveArrArray = m_revit.Create.NewCurveArrArray()
    Dim arr As CurveArray = m_revit.Create.NewCurveArray()
    ‘****** This creates the section for the curb ********
    Dim normal As XYZ = XYZ.BasisZ
    Dim sketchPlane As SketchPlane = CreateSketchPlane(normal, XYZ.Zero)
    Dim pnt1 As XYZ = m_revit.Create.NewXYZ(0, 0, 0)
    Dim pnt2 As XYZ = m_revit.Create.NewXYZ(0, 0.5, 0)
    Dim pnt3 As XYZ = m_revit.Create.NewXYZ(0.5, 0.5, 0)
    Dim pnt4 As XYZ = m_revit.Create.NewXYZ(0.5, -1, 0)
    Dim pnt5 As XYZ = m_revit.Create.NewXYZ(0, -1, 0)
    arr.Append(m_revit.Create.NewLineBound(pnt1, pnt2))
    arr.Append(m_revit.Create.NewLineBound(pnt2, pnt3))
    arr.Append(m_revit.Create.NewLineBound(pnt3, pnt4))
    arr.Append(m_revit.Create.NewLineBound(pnt4, pnt5))
    arr.Append(m_revit.Create.NewLineBound(pnt5, pnt1))
    arrarr.Append(arr)
    Dim profile As SweepProfile = m_revit.Create.NewCurveLoopsProfile(arrarr)
    Dim curves As CurveArray = m_revit.Create.NewCurveArray()
    Dim refArray As ReferenceArray = m_revit.Create.NewReferenceArray
    Dim pt1 As XYZ = m_revit.Create.NewXYZ(-265.9978, -358.3954, 0)
    Dim pt2 As XYZ = m_revit.Create.NewXYZ(-265.9374, -340.4006, 0)
    Dim curve As Curve = m_revit.Create.NewLineBound(pt1, pt2)
    curves.Append(curve)
    refArray.Append(curve.Reference)
    ‘Create the Sweep
    Dim sweep1 As Sweep = m_creationFamily.NewSweep(True, refArray, profile, 0, ProfilePlaneLocation.Start)
    ‘ move to proper place
    Dim transPoint1 As XYZ = m_revit.Create.NewXYZ(11, 0, 0)

    m_familyDocument.Move(sweep1, transPoint1)

    An exception is thrown on the NewSweep method. I have also tried building the Reference array using code like this without any luck:
    refArray.Append(curve.get_EndPointReference(0))
    refArray.Append(curve.get_EndPointReference(1))
    Any help you can provide that allows me to sweep along a 3D path would be GREATLY appreciated.
    Thanks in advance, Mike

  23. Dear Mike,
    Thank you for your interesting question. I have created a draft for a new blog post to answer it and mailed that to you directly for reviewing.
    Cheers, Jeremy.

  24. Dear Mike,
    Here is is now:
    http://thebuildingcoder.typepad.com/blog/2009/08/new-sweep-and-references.html
    Glad that we seem to be moving forward to resolve your issue.
    Cheers, Jeremy.

  25. Hi jeremy I have two queries:
    what does below parameter represents for Ramp?
    Ramps.get_Parameter(BuiltInParameter.RAMP_SLOPE)
    1)Is it giving the values of the x,y cordinates?
    2) How do we get the (x,y,z)cordinates for stairs, ramps ?

  26. Dear Ritish,
    I can see the RAMP_SLOPE built-in parameter enumeration value listed when I look at the enumeration in the development environment, but I do not see it being used in the actual parameters of a ramp in the BIM.
    I looked at a ramp instance, which happens to have an element id of 132281 in my model, and I do not see any RAMP_SLOPE parameter on that.
    I looked at its symbol with id 15922, and I do not see that parameter there either.
    You can get lots of X, Y, Z coordinates for stairs and ramps by querying them for their geometry. The question is what coordinates exactly are you interested in?
    Normally, I would suggest querying the ramp for its location as well, but I do not see that property properly exposed on the ramp object, or at least it does not seem to be a LocationPoint or LocationCurve instance, and therefore the data is probably inaccessible through the API.
    Cheers, Jeremy.

  27. Blogs are so informative where we get lots of information on any topic. Nice job keep it up!!

  28. hi Jeremy,
    i posed an issue on the thread of November 17, 2008 Wall Elevation Profile regarding create new wall w/ CurveArray of more than one “loops” (inner loops are edges of the window/door opennings), sometimes it won’t generate new wall even though temporary model lines generated from CurveArray looks OK.
    i don’t know what exactly causes such issue, sorting of inner loops is my best guess, if so, then what is the rule of loops? outer loop in one direction and all inner loops in another direction? or how to make CurveArray of wall profile correct if inner loops exists?
    my case is simple:
    1) select wall which has window/door(s).
    2) use solid/edge method to get points/lines list (from your sample).
    3) convert to CurveArray.
    4) create new wall w/ opening(s) of window/door(s).
    works great most of time.
    very appreciated for your help!

  29. hi Jeremy,
    even though i’m not quite sure if i’ve already figured out, but seems whenever the 1st edge of outer loop is perpendicular to the 1st edge of inner loop, the NewWall won’t work for the CurveArray based on outer loop + inner loop(s), after i add the following code to “shift” around inner loop(s), then i works, don’t know why?
    // v1 – vector of 1st edge of outer loop
    // v2 – vector of 1st edge of inner loop(s)
    // vertices – inner loop
    while (Math.Abs((v1.Angle(v2) * 180 / Math.PI – 90)) < 0.00001)
    {
    vertices.Insert(0, vertices[vertices.Count – 1]);
    vertices.RemoveAt(vertices.Count – 1);
    v2 = vertices[1].Subtract(vertices[0]);
    }

  30. Dear Ning,
    Thank you for this interesting question. I already discussed it with some colleagues, and the consensus is that it should probably work. Could you submit a complete working Visual Studio solution and the source code that you are using together with examples of situations of where it works and does not work? Thank you!
    Cheers, Jeremy.

  31. Dear Deric,
    Please note that I just published some updated information on access to slanted walls:
    http://thebuildingcoder.typepad.com/blog/2011/03/the-facewall-class-and-slanted-walls.html
    Cheers, Jeremy.

Leave a Reply to NingCancel reply

Discover more from Autodesk Developer Blog

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

Continue reading