Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to get the face reference

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
Anonymous
13529 Views, 7 Replies

How to get the face reference

            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??

Tags (2)
7 REPLIES 7
Message 2 of 8
Joe.Ye
in reply to: Anonymous

Hi

The face retrieved from CalculateSpatialElementGeometry method doesn't contain a valid reference.
I think the face you want to get should belong to other Revit element's face.
So you can get the geometry data from that object. And get the target face from the returned geometry data.

Note: To get the reference of a face that is part of a solid, you need to set Option.ComputeReferences = true.
Here is the short code fragment:

//suppose the face is the floor.

Floor floor = ... //code to get the target floor.
Options opt = new Options();
opt.ComputeReferences = true;
GeometryElement geoElement = floor.get_Geometry(opt);
//Then get the target face from the geoElement object.

Hope this helps,




Joe Ye
Contractor
Developer Technical Services
Autodesk Developer Network
Message 3 of 8
Anonymous
in reply to: Joe.Ye

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;
  }
}

Message 4 of 8
jeremytammik
in reply to: Anonymous

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 Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 5 of 8
Anonymous
in reply to: jeremytammik

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

 

Message 6 of 8
FAIR59
in reply to: Anonymous

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.

Message 7 of 8
Anonymous
in reply to: FAIR59

Thank you so much!  That worked!!!!

Message 8 of 8
juancalvoferrandiz
in reply to: Anonymous

 

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);
}

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community