I'm having trouble to create a roof via code. I know how to create a stairs for example : I start a StairsEditScope and use CreateSketchedLanding with all the right parameters to create my stairs and just commit the StairsEditScope, but for a roof i cant find a clue on how to create it from scratch, any leads?
And if there isnt a way, for example: ceiling i know there isnt a way so i need to use a floor as a ceiling workaround. But for roof i dont have a workaround.
Solved! Go to Solution.
Solved by rosalesduquej. Go to Solution.
Hi onizukabr,
Here is a command to create a roof, Just make sure you have some walls to hold it and also one of your levels is named "Roof".
I created a simple 4 walls rectangle and the selcted them and ran the command that I'm providing.
You can read more about this sample in the Revit Help file, here is the link.
http://help.autodesk.com/view/RVT/2016/ENU/?guid=GUID-33E6A6BD-96AA-4FAF-B660-1DD0C06CCD29
#region Namespaces using System; using System.Collections.Generic; using System.Diagnostics; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using System.Linq; #endregion namespace CreateRoof { [Transaction(TransactionMode.Automatic)] public class Command : IExternalCommand { public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; // Before invoking this sample, select some walls to add a roof over. // Make sure there is a level named "Roof" in the document. // find the Roof level FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfClass(typeof(Level)); var elem = from element in collector where element.Name == "Roof" select element; Level level = elem.Cast<Level>().ElementAt<Level>(0); collector = new FilteredElementCollector(doc); collector.OfClass(typeof(RoofType)); RoofType roofType = collector.FirstElement() as RoofType; // Get the handle of the application Autodesk.Revit.ApplicationServices.Application application = doc.Application; // Define the footprint for the roof based on user selection CurveArray footprint = application.Create.NewCurveArray(); ICollection<ElementId> selectedIds = uidoc.Selection.GetElementIds(); if (selectedIds.Count != 0) { foreach (ElementId id in selectedIds) { Element element = doc.GetElement(id); Wall wall = element as Wall; if (wall != null) { LocationCurve wallCurve = wall.Location as LocationCurve; footprint.Append(wallCurve.Curve); continue; } ModelCurve modelCurve = element as ModelCurve; if (modelCurve != null) { footprint.Append(modelCurve.GeometryCurve); } } } else { throw new Exception("You should select a curve loop, or a wall loop, or loops combination \nof walls and curves to create a footprint roof."); } ModelCurveArray footPrintToModelCurveMapping = new ModelCurveArray(); FootPrintRoof footprintRoof = doc.Create.NewFootPrintRoof(footprint, level, roofType, out footPrintToModelCurveMapping); ModelCurveArrayIterator iterator = footPrintToModelCurveMapping.ForwardIterator(); iterator.Reset(); while (iterator.MoveNext()) { ModelCurve modelCurve = iterator.Current as ModelCurve; footprintRoof.set_DefinesSlope(modelCurve, true); footprintRoof.set_SlopeAngle(modelCurve, 0.5); } return Result.Succeeded; } } }
Let me know how it goes :).
This worked on C#. The problem is i`m working with python ( Dynamo add ) and on python there isnt a way to pass a paramater by reference ( The case with
out footPrintToModelCurveMapping ) so i cant make it work
Have you searched for a solution?
I see many suggestions.
Here is one of them:
http://stackoverflow.com/questions/10541343/ref-out-on-2d-array-with-ironpython
I searched for "ironpython out by reference", e.g., like this:
https://duckduckgo.com/?q=ironpython+out+by+reference
Good luck!
Thanks it worked using:
footPrintToModelCurveMapping = clr.StrongBox[ModelCurveArray]()
it wasn`t a by Reference problem
Dear Gergő,
How do you achieve the desired result manually through the user interface?
Normally, programmatic approach is quite similar.
The procedure for you to explore this yourself is always the same:
Set up a simple minimal starting point situation manually through the user interface.
Explore the existing elements and their properties using RevitLookup, BipChecker, the element lister, and other, more intimate database exploration tools:
Make the desired modification, in this case adding the sloped glazing.
Analyse what changed.
Now you know what you need to do to achieve the desired result.
I hope this helps.
Cheers,
Jeremy
Dear Jeremy, as far as i managed to investigate, a BasicRoof and a SlopedGlazing are the same category, the same creation method should work for them. My code below works fine, if I specify a BasicRoof as the roof type and create the slope of the roof, with the iterator.
It also works fine, if I specify a SlopedGlazing as type, and don't specify slope for the footprint, so a flat sloped glazing is created.
But if I switch the type of the sloped roof from basic, to SlopedGlazing in code, the roof element disappears from the model, without any warning.
Any idea why that's happening?
Thanks, Gergő
public static IEnumerable<FootPrintRoof> RoofCreator(Document doc, IEnumerable<InputRoof> inputRoofs, IEnumerable<Level> levels, IEnumerable<RoofType> roofTypes ) { var levelList = levels.ToList(); var roofTypesList = roofTypes.ToList(); const string roofTemplate = "RoofTemplate"; foreach (var inputRoof in inputRoofs) { var level = levelList.Single(l => l.Name == inputRoof.LevelName); var roofTemp = roofTypesList.Single(r => r.Name == roofTemplate); var footPrintToModelCurveMapping = new ModelCurveArray(); var roof = doc.Create.NewFootPrintRoof(inputRoof.RoofContour, level, roofTemp, out footPrintToModelCurveMapping); var iterator = footPrintToModelCurveMapping.ForwardIterator(); iterator.Reset(); var i = 1; while (iterator.MoveNext()) { i++; var modelCurve = iterator.Current as ModelCurve; if (i % 2 == 0) { roof.set_DefinesSlope(modelCurve, true); roof.set_SlopeAngle(modelCurve, Converter.DegToRad(inputRoof.Slope)); } else { roof.set_DefinesSlope(modelCurve, false); } } var rType = roofTypesList.First(r => r.Name == inputRoof.RoofTypeName); roof.RoofType = rType; Log.Trace(roof.RoofType.Name); yield return roof; } }
What happens if you switch back and forth between basic and glazing manually in the user interface?
Dear Gergő,
Thank you for your update.
Ok. In that case, I'll raise an issue with the development team. Please provide a full reproducible case for me to share with them so they can analyse in depth and verify any fixes that may be required:
http://thebuildingcoder.typepad.com/blog/about-the-author.html#1b
Thank you!
Best regards,
Jeremy
Dear Gergő,
Thank you for your reproducible case.
I logged the issue REVIT-103341 [API: roof creation fails for sloped glazing -- 12373437] with our development team for this on your behalf as it requires further exploration and possibly a modification to our software. Please make a note of this number for future reference.
You are welcome to request an update on the status of this issue or to provide additional information on it at any time quoting this change request number.
This issue is important to me. What can I do to help?
This issue needs to be assessed by our engineering team, and prioritised against all of the other outstanding change requests. Any information that you can provide to influence this assessment will help. Please provide the following where possible:
This information is extremely important. Our engineering team have limited resources, and so must focus their efforts on the highest impact items. We do understand that this will cause you delays and affect your development planning, and we appreciate your cooperation and patience.
Best regards,
Jeremy
Can't find what you're looking for? Ask the community or share your knowledge.