SpatialElementGeometryResults results = calculator.CalculateSpatialElementGeometry((SpatialElement)room); ElementCategoryFilter ceilingCategoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_Ceilings); // Get solid geometry so we can examine each face Solid solid = results.GetGeometry(); if (solid != null) { // Traverse each face in the spatial element volume FaceArray faces = solid.Faces; foreach (Face face in faces) { IList<SpatialElementBoundarySubface> subfaces = results.GetBoundaryFaceInfo(face); foreach (SpatialElementBoundarySubface subface in subfaces) { if (subface.SubfaceType == SubfaceType.Top) { f_boundaryElement.Add(subface.GetBoundingElementFace()); } } } }
From above code, I can get a face f_boundaryElement[0]. I want to insert a familyinstance in this face. the face returned (f_boundaryElement[0]) does not include a reference. However, to use "NewFamiliyinstance(face, xyz,xyz, familySymbol)" requres the face has a reference. So, How can I get a face (i.e., ceiling face) with reference from above code??
Solved! Go to Solution.
Solved by Joe.Ye. Go to Solution.
I realize this is an older post, but I was hoping to get some help with a similar issue.
Do you know what would cause the error of a null GeometryElement?
Sometimes the code works for me and sometimes it doesn't.
//Creating the Floor
CurveArray flrCurves = new CurveArray();
flrSt = new XYZ(startPoint.X + massWidthDbl, startPoint.Y, startPoint.Z);
flr02Pt = startPoint;
flr03Pt = new XYZ(startPoint.X, startPoint.Y - massLengthDbl, startPoint.Z);
flr04Pt = new XYZ(startPoint.X + massWidthDbl, startPoint.Y - massLengthDbl, startPoint.Z);
flrCurves.Append(Line.CreateBound(flrSt, flr02Pt));
flrCurves.Append(Line.CreateBound(flr02Pt, flr03Pt));
flrCurves.Append(Line.CreateBound(flr03Pt, flr04Pt));
flrCurves.Append(Line.CreateBound(flr04Pt, flrSt));
floorType = GetFloorType(doc, "FIN_Wood 3/4\" (6\" Plank)", out flrThk);
finishedFloor = doc.Create.NewFloor(flrCurves, floorType, modLevel, false, XYZ.BasisZ);
//Getting Floor Geometry
Face face = null;
Options geomOptions = new Options();
geomOptions.ComputeReferences = true;
geomOptions.DetailLevel = ViewDetailLevel.Medium;
GeometryElement faceGeom = finishedFloor.get_Geometry(geomOptions);
foreach (GeometryObject geomObj in faceGeom)
{
Solid geomSolid = geomObj as Solid;
if (null != geomSolid)
{
foreach (Face geomFace in geomSolid.Faces)
{
face = geomFace;
break;
}
break;
}
}
Dear Elisabeth,
A Revit element geometry can consist of various parts split up into a whole hierarchy of geometry objects.
Some of the geometry objects end up being present and still being null, because they have no content.
You may need to iterate further to find all the different pieces.
You can explore your specific element geometry interactively in RevitLookup, or you can debug through the Revit SDK sample ElementViewer to see what steps it takes to retrieve and display all the geometrical components of a specific element.
Cheers,
Jeremy
Jeremy,
I am still having some issues with this. Not quite sure how to solve my problem. I thought it might be helpful if I elaborate a little further. Under a single transaction, I am placing a floor, getting its geometry (faces), then placing a faced-based toilet family on the floor. This happens all before the transaction is committed.
The user is given two options: they can create LAYOUT C (ModTypeStr.Equals("C")): which includes kitchen, laundry, and bathroom or LAYOUT B (ModTypeStr.Equals("B")): which includes bedroom, hallway, and bathroom. Each of these units (walls, floor, doors, etc.) are all built with the same code with if statements that make the location points different based on the users selection. If the user selects LAYOUT C there are not issues, but if the user selects LAYOUT B, the Geometry Element of the floor comes back null. If I am creating the floor the exact same way, how can it come back null only for LAYOUT B? I am so confused!! 😞
If I choose not to install the toilet, the floor is placed correctly. After doing this, I use the RevitLookup tool (WHICH IS AMAZING - THANKS) and I am able to see the floor which was created. It has faces and geometry. Not sure why I can't get to it. I researched GetSymbolGeometry thinking maybe this is what I needed to be using but if I am getting a null GeometryElement, I am unsure on how I can initialize the GetSymbolGeometry method.
Thanks in advance for all of your help!
Elizabeth
(email address changed)
Code Dump --- Placing Floor
#region Place Floor //Start array for floor and Create Floor CurveArray flrCurves = new CurveArray(); flrSt = new XYZ(startPoint.X + massWidthDbl, startPoint.Y, startPoint.Z); flr02Pt = startPoint; flr03Pt = new XYZ(startPoint.X, startPoint.Y - massLengthDbl, startPoint.Z); flr04Pt = new XYZ(startPoint.X + massWidthDbl, startPoint.Y - massLengthDbl, startPoint.Z); flrCurves.Append(Line.CreateBound(flrSt, flr02Pt)); flrCurves.Append(Line.CreateBound(flr02Pt, flr03Pt)); flrCurves.Append(Line.CreateBound(flr03Pt, flr04Pt)); flrCurves.Append(Line.CreateBound(flr04Pt, flrSt)); floorType = GetFloorType(doc, "FIN_Wood 3/4\" (6\" Plank)", out flrThk); finishedFloor = doc.Create.NewFloor(flrCurves, floorType, modLevel, false, XYZ.BasisZ); finishedFloor.get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM).Set(0); //Need to get the instance so instance parameters can be fetched finFlrElement = doc.GetElement(finishedFloor.Id); finFlrInst = finFlrElement as Floor; //Attach Module Guid to Floor modGuid = finFlrInst.get_Parameter(ModuleGuid); if (modGuid == null) { MessageBox.Show(paramEx.Message, "Revit Preparation Incomplete!"); throw paramEx; } modGuid.Set(guid.ToString()); //Add Floor to Group grpIDList.Add(finishedFloor.Id); #endregion
Code Dump -- Placing Toilet
#region Place Toilet //Check to see if Toilet Family exists and Create if (modTypeStr.StartsWith("B") || modTypeStr.StartsWith("C")) { Family toiletFam = null; FamilySymbol toileSymbol = null; fileName = @"C:\MyDrive\Revit_2016\Families\Toto_Aquia_Toilet.rfa"; familyName = "Toto_Aquia_Toilet"; famExists = DoesFamilyExist(doc, fileName, familyName, out toiletFam); if (famExists == false) toiletFam = LoadFamilySubT(doc, fileName, familyName); ISet<ElementId> toiletFamIds = toiletFam.GetFamilySymbolIds(); foreach (ElementId id in toiletFamIds) { toileSymbol = toiletFam.Document.GetElement(id) as FamilySymbol; if (!toileSymbol.IsActive) toileSymbol.Activate(); break; } toilet = null; if (modTypeStr.StartsWith("B")) { toiletLoc = new XYZ(LaundryRSt.X + (intLaundryRWallThk * 0.5) + 1.5, startY + wall01Thk, flrSt.Z); toiletPt2 = toiletLoc.Add(XYZ.BasisZ); } else if (modTypeStr.StartsWith("C")) { toiletLoc = new XYZ(BWall02St.X + (wall02dThk * 0.5) + 1.9634, BWall02St.Y + (intToiletWallThk * 0.5), flrSt.Z); toiletPt2 = toiletLoc.Add(XYZ.BasisZ); } toiletAxis = Line.CreateBound(toiletLoc, toiletPt2); //Get Face of floor for toilet because it is a face-based family. Face face = null; Autodesk.Revit.DB.Options geomOptions = new Autodesk.Revit.DB.Options(); geomOptions.View = doc.ActiveView; geomOptions.ComputeReferences = true; GeometryElement faceGeom = finishedFloor.get_Geometry(geomOptions); foreach (GeometryObject geomObj in faceGeom) { Solid geomSolid = geomObj as Solid; if (null != geomSolid) { foreach (Face geomFace in geomSolid.Faces) { face = geomFace; break; } break; } } // Get the center of the wall BoundingBoxUV bboxUV = face.GetBoundingBox(); UV center = (bboxUV.Max + bboxUV.Min) / 2.0; XYZ normal = face.ComputeNormal(center); XYZ refDir = normal.CrossProduct(XYZ.BasisZ); toilet = doc.Create.NewFamilyInstance(face, toiletLoc, refDir, toileSymbol); if (modTypeStr.StartsWith("B")) { toilet.IsWorkPlaneFlipped = true; ElementTransformUtils.RotateElement(doc, toilet.Id, toiletAxis, mathMethods.DegreesToRadians(0.0)); } else if (modTypeStr.StartsWith("C")) { toilet.IsWorkPlaneFlipped = true; ElementTransformUtils.RotateElement(doc, toilet.Id, toiletAxis, mathMethods.DegreesToRadians(180.0)); } if (toilet != null) { //Attach Module GUID modGuid = toilet.get_Parameter(ModuleGuid); try { modGuid.Set(guid.ToString()); } catch { MessageBox.Show(paramEx.Message, "Revit Preparation Incomplete!"); throw paramEx; } //Add to Group grpIDList.Add(toilet.Id); } } #endregion
when you create a floor (or other element) Revit calculates the geometry on transaction.commit(). You need the geometry before that, so you have to call document.Regenerate() after the creation if the floor.
Hello,
I get null with the Reference property from faces obtain from a Solid created by a Extrusion.
Does these faces have References ?
How I incorporate the options without using a get_Geometry method?
Thanks for your help.
var geometry = GeometryCreationUtilities.CreateExtrusionGeometry(listCurveLoop, Door.HandOrientation, Door.Symbol.get_Parameter(BuiltInParameter.WINDOW_WIDTH).AsDouble()); var facesArray = geometry.Faces; List<PlanarFace> facesList = facesArray.OfType<PlanarFace>().ToList(); var refenrencesList = new List<Reference>(); foreach (var face in facesList) { refenrencesList.Add(face.Reference); }