Hi
I'm a bit out of my comfort zone here. I am creating an addin which involves creating a mass for each instance of room. I cobbled together the code below from examples on other blogs / sites (mostly here). This works but only if the room hasn't got any internal boundaries (holes, islands, etc). If a room has an internal boundary the actual NewExtrution line fails with the error "One of the conditions for the inputs was not satisfied. Consult the documentation for requirements for each argument.". I'm guessing this is because the profile array has more than one profile (like internal boundaries in this case). The boundaries don't overlap though, just some are entirely consumed by others.
Anyone know of a better approach here? Or how to amend the code below to deal with the internal boundaries (holes) in the room?
// Create family doc from template Autodesk.Revit.DB.Document familyDoc = app.NewFamilyDocument(@"C:\ProgramData\Autodesk\RVT 2013\Family Templates\English\Metric Generic Model.rft"); // Save the new Family - room is Room Element not defined in this sample code string fileName = @"C:\Temp\" + room.UniqueId.ToString() + ".rfa"; familyDoc.SaveAs(fileName); Transaction transaction = new Transaction(familyDoc, "RoomToMass"); transaction.Start(); // Get the room boundary SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions(); IList<IList<Autodesk.Revit.DB.BoundarySegment>> segArray = room.GetBoundarySegments(opt); CurveArray curveArray = new CurveArray(); // Iterate to gather the curve objects foreach (IList<Autodesk.Revit.DB.BoundarySegment> bSegments in segArray) { foreach (Autodesk.Revit.DB.BoundarySegment bSegment in bSegments) { curveArray.Append(bSegment.Curve); } } // Origin point and normal point that gives the extrusion direction XYZ ptOrigin = new XYZ(0, 0, 0); XYZ ptNormal = new XYZ(0, 0, 1); // The plane to extrude the mass from Plane plane = app.Create.NewPlane(ptNormal, ptOrigin); SketchPlane sketchPlane = familyDoc.FamilyCreate.NewSketchPlane(plane); // Add the CurveArray to a CurveArrArray CurveArrArray curveArrArray = new CurveArrArray(); curveArrArray.Append(curveArray); // Extrude the form 10 feet as test Extrusion extrusion = familyDoc.FamilyCreate.NewExtrusion(true, curveArrArray, sketchPlane, 10); transaction.Commit(); familyDoc.Save(); // now need to place the family...
Solved! Go to Solution.
Solved by saikat. Go to Solution.
Hello Graham
Is it an option to create new model lines that outline the outer periphery/shell of the room using the room's boundary segments (instead of directly using the curves of the room boundary segments) and then use this set of curves in a curvearray to create the mass element.
cheers
Saikat
Thanks for looking at my post.
Yes that would be an option i could look at. If i knew how to just get the boundary of the OUTER edge only - ignoring all the inner boundaries. Any Pointers?
Cheers
Graham
Hello Graham
Would an approach similar to what is being discussed here be of help/use:
http://thebuildingcoder.typepad.com/blog/2008/12/2d-polygon-areas-and-outer-loop.html
Do let us know if this worked out or not. Or if you found any other approach, better still.
cheers
Thank you Saikat. In this case i went with assuming the first segment set in the collection was the outer boundary and inserted a break in the first foreach loop to force a break after first loop. I've tested on hundreds of rooms and the first segment set has always been the outer edge (so far). I would like to eventually include holes within the mass but for this particular problem just the outer edge will suffice.
Cheers
Graham
Great! Thanks for the update.
kind regards
I am trying to comile this code in Visual Studio Express 2013.
I need to compile for Revit 2014
What is the Class that goes avove this code block?
// Origin point and normal point that gives the extrusion direction XYZ ptOrigin = new XYZ(0, 0, 0); XYZ ptNormal = new XYZ(0, 0, 1);
What are the classes I need to incorporate to make this code work for Revit 2014 addin
Also, can I compile this for Dynamo?
I think the code as pasted above is missing the following class:
public Extrusion NewExtrusion(
bool isSolid,
CurveArrArray profile,
SketchPlane sketchPlane,
double end
)
I believe this Code will retrieve the flat extrusion of a room object.
Sometimes rooms are cut off by pitched roofs.
If Get Geometry is used from the API, can the Room Solids be simply be put into a mass family?
See below example of beam.get_Geometry(options)
Is it possible to use rooms.get_Geometry(options):
public void GetCurvesFromABeam(Autodesk.Revit.DB.FamilyInstance beam, Autodesk.Revit.DB.Options options) { Autodesk.Revit.DB.GeometryElement geomElem = beam.get_Geometry(options); Autodesk.Revit.DB.CurveArray curves = new CurveArray(); Autodesk.Revit.DB.SolidArray solids = new SolidArray(); //Find all solids and insert them into solid array AddCurvesAndSolids(geomElem, ref curves, ref solids); } private void AddCurvesAndSolids(Autodesk.Revit.DB.GeometryElement geomElem, ref Autodesk.Revit.DB.CurveArray curves, ref Autodesk.Revit.DB.SolidArray solids) { foreach (Autodesk.Revit.DB.GeometryObject geomObj in geomElem) { Autodesk.Revit.DB.Curve curve = geomObj as Autodesk.Revit.DB.Curve; if (null != curve) { curves.Append(curve); continue; } Autodesk.Revit.DB.Solid solid = geomObj as Autodesk.Revit.DB.Solid; if (null != solid) { solids.Append(solid); continue; } //If this GeometryObject is Instance, call AddCurvesAndSolids Autodesk.Revit.DB.GeometryInstance geomInst = geomObj as Autodesk.Revit.DB.GeometryInstance; if (null != geomInst) { Autodesk.Revit.DB.GeometryElement transformedGeomElem = geomInst.GetInstanceGeometry(geomInst.Transform); AddCurvesAndSolids(transformedGeomElem, ref curves, ref solids); } } }