原文链接(The Building Coder: Jeremy Tammik)
我们的目标是在一个新建的族中,对一个Family Instance进行镜像。我们已经讨论过【元素镜像】和【访问一个新建元素】,但是在一个新建的族文档中进行这些操作有些不同。
第一个问题是镜像命令需要一个当前活动视图作为参数。而活动视图在族文档中不是自动呈现的。Joe(译者注:叶雄进)找到了一个解决办法,通过ShowElements方法来曲线实现对当前活动视图的指定。不过这个方法有个副作用:会产生一个不需要的警告消息。所以第二个问题是如何消除这个伴生的警告消息。
正如你接下来将会看到的,你可以使用ShowElements方法来改变当前的活动视图,甚至在族文档和项目文档之间切换。官方的Revit 2011 API不提供任何方式来切换活动视图(译者注:Revit 2012 API弥补了这一缺陷)。
最初的问题是这样的:
【问题】我想要创建一个新族:Profile-Mullion.rfa,插入一些详细的构件,然后沿垂直轴对它们进行镜像。当我试图镜像一个构件的Family Instance时,Revit抛出一个异常:无效的活动视图。我的族文档的活动视图总是为NULL,因为这个族文档是我用Application.NewDocument()在代码中动态创建的。我尝试用代码改变当前动态视图,但是Document.ActiveView属性是只读的。有什么办法可以解决这个问题吗?我还尝试过Mirror(Element, Reference)和Mirror(Element, Line),不过它们都会导致相同的异常。
【解答】指定当前活动视图的思路是:在指定视图的参考平面上创建一条线段(DetailLine)。然后使用ShowElement()方法显示该线段,则Revit会自动切换其活动视图到该线段所在的视图。至于该方法导致的警告对话框,可以使用DialogBoxShowing事件来处理掉。实现代码如下:
Public Shared Function NewFamilySymbol( _ ByVal projectDoc As Document) _ As FamilySymbol Dim app As Autodesk.Revit.ApplicationServices _ .Application = projectDoc.Application Dim templateFileName As String _ = "C:\Program Files\Autodesk" _ + "\Revit Architecture 2011" _ + "\Content\Imperial Templates" _ + "\Profile-Mullion.rft" Dim familyDoc As Document _ = app.NewFamilyDocument(templateFileName) If familyDoc Is Nothing Then Dim tdError As New TaskDialog("Error") tdError.MainInstruction = "Could not find" _ + " family template: Profile-Mullion.rft" tdError.MainContent = "Designated path '" _ + templateFileName + "' is invalid." tdError.CommonButtons _ = TaskDialogCommonButtons.Close tdError.Show() Return Nothing End If ' Store some elements in the original project ' that we can use later (that are in the ' current ActiveView) Dim projDocCollector As New _ FilteredElementCollector( _ projectDoc, projectDoc.ActiveView.Id) Dim projFamInsts As List(Of ElementId) _ = projDocCollector.OfClass( _ GetType(FamilyInstance)) _ .ToElementIds Dim famDocCollector As New _ FilteredElementCollector(familyDoc) Dim views As List(Of Element) _ = famDocCollector _ .OfClass(GetType(View)) _ .ToElements Dim planView As View = Nothing ' Find the default view For Each v As View In views If v.Name = "Ref. Level" Then planView = v Exit For End If Next Dim fileName As String = Nothing Dim familyDocTrans As New Transaction( _ familyDoc, "CreateFamilySymbol") familyDocTrans.Start() Dim famUIdoc As New UIDocument(familyDoc) ' ... Create FamilyInstances in the familyDoc ' Mirror elements about vertical centerline Dim origin As New XYZ(0, 0, 0) Dim pt As New XYZ(0, 1, 0) Dim vertAxis As Line = app.Create.NewLine( _ origin, pt, True) Dim detLine As DetailLine = familyDoc _ .FamilyCreate.NewDetailCurve( _ planView, vertAxis) ' Set up event handler to automatically ' click "OK" when the ShowElements dialog ' box appears CGlobal.SuppressDialogBoxes = True Try ' Transfer the active view to the ' Family(Document) famUIdoc.ShowElements(detLine) familyDoc.Mirror(detailComps, vertAxis) ' Delete the old family instance familyDoc.Delete(detailComps) Catch ex As Exception End Try ' Delete the detail line familyDoc.Delete(detLine) ' Transfer the active view back to the project Dim projUIdoc As New UIDocument(projectDoc) projUIdoc.ShowElements(projFamInsts.Item(0)) ' Reset the dialog box event handler CGlobal.SuppressDialogBoxes = False familyDocTrans.Commit() ' Define a save path for the new family If familyDoc.SaveAs(fileSavePath) Then ' Bring the family into the current project projectDoc.LoadFamily( _ fileSavePath, projectFam) ' Close the family edit, ' do not save changes familyDoc.Close(False) ' Return Family or FamilySymbol End Function