Hi,
Using 'thebuildingcoder' blog I am trying to create some dimensions between familyinstances (Generic Model face based) but I am having no luck. For the selected familyinstances (generic model face based) no references are returned. But when I select a structural column (familyinstance) the code will return a reference.
I have converted the sample from C# to VB.NET.
Code in C#
_opt = new Options();
_opt.ComputeReferences = true;
_opt.IncludeNonVisibleObjects = true;
static Reference GetFamilyInstancePointReference(
FamilyInstance fi )
{
return fi.get_Geometry( _opt )
.OfType<Point>()
.Select<Point, Reference>( x => x.Reference )
.FirstOrDefault();
}
Code in VB.NET
Dim _opt As Options = Nothing
_opt = New Options()
_opt.ComputeReferences = True
_opt.IncludeNonVisibleObjects = True
Shared Function GetFamilyInstancePointReference(ByVal fi As FamilyInstance) As Reference
Return fi.Geometry(_opt).OfType(Of Point)() _
.Select(Function(x) x.Reference) _
.FirstOrDefault()
End Function
Using RevitLookup (Snoop) I can not seem to find 'point' in the geometry element collection (only GeometryInstance is show). However when I snoop a familyinstance of a structural column 'point' will show up and the code is able to return references. Am I doing something wrong of is this not possible for Generic model facebased instances? I am using Revit 2015.
regards,
Raymond
Solved! Go to Solution.
Solved by Scott_Wilson. Go to Solution.
Solved by Scott_Wilson. Go to Solution.
Hi Aaron,
Please find a family as an attachment. I picked a random family from our library. Last week I created a new family from scratch (Generic Model face based) which also does not return any references.
Regards,
Raymond
Sometimes we can't rely on RevitLookup 😞
Try this:
doc = commandData.Application.ActiveUIDocument.Document; var uiSel = commandData.Application.ActiveUIDocument.Selection; foreach (var elementId in uiSel.GetElementIds()) { Element element = doc.GetElement(elementId); if (element != null) { Options options = new Options(); options.ComputeReferences = true; options.IncludeNonVisibleObjects = true; if (element.Document.ActiveView != null) options.View = element.Document.ActiveView; else options.DetailLevel = ViewDetailLevel.Fine; var geoElem = element.get_Geometry(options); foreach (var item in geoElem) { Solid solidObj = item as Solid; if (solidObj != null && solidObj.Faces.Size > 0) { } else { GeometryInstance geoInst = item as GeometryInstance; if (geoInst != null) { GeometryElement geoElemTmp = geoInst.GetInstanceGeometry(); foreach (GeometryObject geomObjTmp in geoElemTmp) { Solid solidObj2 = geomObjTmp as Solid; if (solidObj2 != null && solidObj2.Faces.Size > 0) { // you will see geometry object here !!! } } } } } } else { TaskDialog.Show("ERROR", "Element " + elementId + " is not found"); } }
Thank you for your response and the code. I am not so good with C# so I have converted it to VB.NET. The code loops through solids and it's faces but I am trying to select the non-visible 'defines origin' reference planes. Can I also do that with the provided code?
The family consists of 4 solid objects and a centerline (modelline) but indeed that is not what I am looking for. I am trying to select the invisible reference planes a user uses when placing dimensions, aligning object, etc.
Somehow I can not seem to find these invisible computed references. Saying that .. it seems that the options (.geometry(options)) are not working for a generic model face based familyinstance. Perhaps I can use the lineobjects for my purposes as a workaround.
Here's the method I use for building a custom reference for a FamilyInstance for a particular index value. just plug in the shape handle reference index that can be found by dumping an existing dimension reference
public static Reference GetFamilyReferenceByIndex(FamilyInstance inst, int idx) { Reference indexRef = null; if(inst != null) { Document dbDoc = inst.Document; Options geomOptions = dbDoc.Application.Create.NewGeometryOptions(); if(geomOptions != null) { geomOptions.ComputeReferences = true; geomOptions.DetailLevel = ViewDetailLevel.Undefined; geomOptions.IncludeNonVisibleObjects = true; } GeometryElement gElement = inst.get_Geometry(geomOptions); GeometryInstance gInst = gElement.First() as GeometryInstance; String sampleStableRef = null; String customStableRef = null; if(gInst != null) { GeometryElement gSymbol = gInst.GetSymbolGeometry(); if(gSymbol != null && gSymbol.Count() > 0) { Solid solid = gSymbol.First() as Solid; Face face = solid.Faces.get_Item(0); sampleStableRef = face.Reference.ConvertToStableRepresentation(dbDoc); if(sampleStableRef != null) { String[] tokenList = sampleStableRef.Split(new char[] { ':' }); customStableRef = tokenList[0] + ":" + tokenList[1] + ":" + tokenList[2] + ":" + tokenList[3] + ":" + idx.ToString(); indexRef = Reference.ParseFromStableRepresentation(dbDoc, customStableRef); GeometryObject geoObj = inst.GetGeometryObjectFromReference(indexRef); if(geoObj != null) { String finalToken = ""; if(geoObj is Edge) { finalToken = ":LINEAR"; } if(geoObj is Face) { finalToken = ":SURFACE"; } customStableRef += finalToken; indexRef = Reference.ParseFromStableRepresentation(dbDoc, customStableRef); } else { indexRef = null; } } } else { throw new Exception("No Symbol Geometry found..."); } } } return indexRef; }
have fun
Ok, I've made an interesting discovery...
I was under the impression that the reference indecies were allocated arbitrarily or were simply in order of creation but I have just discovered that the first 9 positions are occupied by the special references that have been allocated in the family editor the list is as follows:
0 = Left
1 = Center Left/Right
2 = Right
3 = Front
4 = Centre Front/Back
5 = Back
6 = Bottom
7 = Centre Elevation
8 = Top
As you can see this sequence matches the order they appear in the family editor reference type drop-down list.
I believe these to be reserved positions within the geometry reference table based on the following observations.
If you edit a family and create a reference plane or edit an existing plane and set it to one of the special reference types above you will see that it will then be available at the corresponding index, this, so far is true for all families I have tried it on.
If you create a dimension to one of these references, 'Left' for example, then edit the family and place a new Reference Plane and allocate it as the 'Left' Reference you will notice that the original reference plane has been set to Not A Reference, which to me signifies that the new reference has now taken the original's position in the reference table. When you load the modified family back into the project, the dimension will now update to reference the new 'Left' Plane
Here's the updated method that should return the correct special reference selected from an enumeration for any family that has it defined.
public enum SpecialReferenceType { Left = 0, CenterLR = 1, Right = 2, Front = 3, CenterFB = 4, Back = 5, Bottom = 6, CenterElevation = 7, Top = 8 } public static Reference GetSpecialFamilyReference(FamilyInstance inst, SpecialReferenceType refType) { Reference indexRef = null; int idx = (int)refType; if(inst != null) { Document dbDoc = inst.Document; Options geomOptions = dbDoc.Application.Create.NewGeometryOptions(); if(geomOptions != null) { geomOptions.ComputeReferences = true; geomOptions.DetailLevel = ViewDetailLevel.Undefined; geomOptions.IncludeNonVisibleObjects = true; } GeometryElement gElement = inst.get_Geometry(geomOptions); GeometryInstance gInst = gElement.First() as GeometryInstance; String sampleStableRef = null; if(gInst != null) { GeometryElement gSymbol = gInst.GetSymbolGeometry(); if(gSymbol != null) { foreach(GeometryObject geomObj in gSymbol) { if(geomObj is Solid) { Solid solid = geomObj as Solid; if(solid.Faces.Size > 0) { Face face = solid.Faces.get_Item(0); sampleStableRef = face.Reference.ConvertToStableRepresentation(dbDoc); break; } } else if(geomObj is Curve) { Curve curve = geomObj as Curve; sampleStableRef = curve.Reference.ConvertToStableRepresentation(dbDoc); break; } else if(geomObj is Point) { Point point = geomObj as Point; sampleStableRef = point.Reference.ConvertToStableRepresentation(dbDoc); break; } } } if(sampleStableRef != null) { String[] refTokens = sampleStableRef.Split(new char[] { ':' }); String customStableRef = refTokens[0] + ":" + refTokens[1] + ":" + refTokens[2] + ":" + refTokens[3] + ":" + idx.ToString(); indexRef = Reference.ParseFromStableRepresentation(dbDoc, customStableRef); GeometryObject geoObj = inst.GetGeometryObjectFromReference(indexRef); if(geoObj != null) { String finalToken = ""; if(geoObj is Edge) { finalToken = ":LINEAR"; } if(geoObj is Face) { finalToken = ":SURFACE"; } customStableRef += finalToken; indexRef = Reference.ParseFromStableRepresentation(dbDoc, customStableRef); } else { indexRef = null; } } } else { throw new Exception("No Symbol Geometry found..."); } } return indexRef; }
enjoy.