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;
最後的測試成功的圖片