Revit二次开发之 有点时间 分析一下Reference
Reference 是Revit对象的引用 也是二次开发必须了解和熟练掌握的技能之一,对象引用包括 图元基础引用 可以根据此引用 实现图元转化 参数信息过滤和设置,此外对于标注来说更重要的是 Face-面引用 Curve-线引用 Point-点引用。
那么根据Revit版本的不同对象的引用获取 也会有所不同 需要查找API做相应的匹配,如 轴线的引用在2014版时还可以通过点引用获得Grid grid = doc.GetElement(refer) as Grid;grid.Curve.GetEndPointReference(0)
grid.Curve.GetEndPointReference(1),模型线和详图线也可以利用此方法获得
那么在2016版就失灵了 但是可以通过Reference reference = new Reference(grid);获得轴线的引用,管线和导线都是如此。
最近遇到了一个棘手的问题 比如一个再平庸不过的长方体 或 是消防喷头 如果我们要标注它们的中心该怎么做呢,起初我利用族实例的集合对象 获得族实例的点来做标注 但是不是所有的族实例都可以找到那个引用点,比如长方体就不行 ,而喷头就可以,示例如下:
UIApplication uiapp = commandData.Application;
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
Autodesk.Revit.DB.View view = doc.ActiveView;
Transaction ts2 = new Transaction(doc, "BIM");
ts2.Start();
Reference refer = uidoc.Selection.PickObject(ObjectType.Element, "");
FamilyInstance instance = doc.GetElement(refer) as FamilyInstance;
LocationPoint location = instance.Location as LocationPoint;
XYZ xyz = location.Point;
Reference refer2 = uidoc.Selection.PickObject(ObjectType.Element, "");
FamilyInstance instance2 = doc.GetElement(refer2) as FamilyInstance;
LocationPoint location2 = instance2.Location as LocationPoint;
XYZ xyz2 = location2.Point;
//获得引用的点
Reference reference = instance.get_Geometry(option).OfType(Point)().Select(Point, Reference)(o => o.Reference).First();
//获得引用的点
Reference reference2 = instance2.get_Geometry(option).OfType(Point)().Select(Point, Reference)(o => o.Reference).First();
Line line = Line.CreateBound(xyz, xyz2);
ReferenceArray refarray = new ReferenceArray();
refarray.Append(reference);
refarray.Append(reference2);
doc.Create.NewDimension(doc.ActiveView, line, refarray);
当然对于我们想标注喷头之间的距离 现在看来是可以实现的,不过后来发现 如果这个喷头连接管道后 那么原先获得那个引用点就被占用了 就再也过滤不到了 那怎么办呢,后来看到Autodesk的一篇博文后才找到解决办法.
其实我们可以获得族实例的参照引用也就是族样板里的那两条中心参照线如下图:
那么怎么获得呢?大家应该知道 其实图元引用是可以转化为字符串的 reference.ConvertToStableRepresentation(doc) 在使用是可以转化回来Reference.ParseFromStableRepresentation(doc, string),那么和我们说的问题有什么关系呢,答案是肯定的 有!根据Autodesk的指引 ,我们分别获得实例的本身引用和实例的几何面或边的引用 转化为字符串后看看有什么不同:如下
实例本身引用
a77b1edc-61fc-4855-8179-b72c50bdd617-00072e8b
实例几何面引用
a77b1edc-61fc-4855-8179-b72c50bdd617-00072e8b:0:INSTANCE:a77b1edc-61fc-4855-8179-b72c50bdd617-00072cc7:9:SURFACE
我们可以看到 几何内部的引用 信息要比实例本身多的多,而且利用“:”号分隔,都是什么意思呢
第一段,很显然和实例本身的引用相同 也就是族实例的UniqueId
第二段,应该是 实例的集合索引 这里应该会保持为零 因为只有一个实例被选中 索引为零
第三段,表明这个引用是Instance内部的 也就是来自于实例的几何图形的引用
第四段,就是最重要的一段 它标示得到的引用是族内部的那个参照 如 前,后, 左, 右,上,下 等共有九个
第五段,指的是引用是几何图形的面或边或点的引用
所以我们只要改变第四段的索引值就可以获得相对应的是参照引用了 就可以标注尺寸了
这里不详细叙述了 把是参照的9个选项设为枚举类型:
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(Document doc, FamilyInstance instance, SpecialReferenceType ReferenceType)
{
Reference indexReference = null;
int index = (int)ReferenceType;
Options geomOptions = new Options();
geomOptions.ComputeReferences = true;
geomOptions.DetailLevel = ViewDetailLevel.Medium;
geomOptions.IncludeNonVisibleObjects = true;
GeometryElement geoElement = instance.get_Geometry(geomOptions);
foreach (GeometryObject obj in geoElement)
{
if (obj is GeometryInstance)
{
GeometryInstance geoInstance = obj as GeometryInstance;
String sampleStableRef = null;
if (geoInstance != null)
{
GeometryElement geoSymbol = geoInstance.GetSymbolGeometry();
if (geoSymbol != null)
{
foreach (GeometryObject geomObj in geoSymbol)
{
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(doc);
break;
}
}
}
}
if (sampleStableRef != null)
{
String[] refTokens = sampleStableRef.Split(new char[] { ':' });
String customStableRef = refTokens[0] + ":" + refTokens[1] + ":" + refTokens[2] + ":" + refTokens[3] + ":" + index.ToString();
indexReference = Reference.ParseFromStableRepresentation(doc, customStableRef);
}
break;
}
else
{
}
}
}
return indexReference;
}
最后调用主函数 实现标注
UIApplication uiapp = commandData.Application;
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
Autodesk.Revit.DB.View view = doc.ActiveView;
Transaction ts = new Transaction(doc, "BIM");
ts.Start();
Reference refer = uidoc.Selection.PickObject(ObjectType.Element, "");
FamilyInstance instance = doc.GetElement(refer) as FamilyInstance;
LocationPoint location = instance.Location as LocationPoint;
XYZ xyz = location.Point;
Reference reference = GetSpecialFamilyReference(doc,instance, SpecialReferenceType.CenterLR);
Reference refer2 = uidoc.Selection.PickObject(ObjectType.Element, "");
FamilyInstance instance2 = doc.GetElement(refer2) as FamilyInstance;
LocationPoint location2 = instance2.Location as LocationPoint;
XYZ xyz2 = location2.Point;
Reference reference2 = GetSpecialFamilyReference(doc, instance2, SpecialReferenceType.CenterLR);
Line line = Line.CreateBound(xyz, xyz2);
ReferenceArray refarray = new ReferenceArray();
refarray.Append(reference);
refarray.Append(reference2);
doc.Create.NewDimension(doc.ActiveView, line, refarray);
ts.Commit();
return Result.Succeeded;
最后的测试成功的图片