Building Coder 链接:http://thebuildingcoder.typepad.com/blog/2010/06/set-tag-type.html
Revit 二次开发论坛链接:http://revit.5d6d.com/viewthread.php?tid=1292&page=1&extra=#pid1814
对设置标签类型这个问题的研究让我有机会重新回顾了之前分别讨论过的几个主题。我觉得有必要将它们在这个新问题中整理一下呈现给大家。
1. 在创建墙体时决定墙体的顶层(Top Level)和底层(Bottom Level);
2. 创建一个新墙体时设置它的顶层边缘;
3. 获取墙体厚度(用于之后计算标签放置位置);
4. 获取门类型(用户在墙体中插入一个门实例);
5. 在墙体中部插入一个门实例;
6. 创建一个和门实例关联的门标签;
7. 获取一个现有的门标签类型(用于复制);
8. 通过复制创建一个新的门标签类型;
9. 将现有门标签的类型设置为新创建的标签类型。
实现 1~6 步的代码我们在 Lab2_0_CreateLittleHouse 外部命令中已经讨论过了。关于 Duplicate() 方法,我们在讨论创建墙体、柱子等元素的时候也都涉及过。
为了讨论本主题,我的代码中还是有些新东西的:几个简洁实用的辅助函数。鉴于此,我觉得有必要将这些新老代码整合到一个独立的外部命令中。
不过还是先让我们看看本主题的来龙去脉吧。
问题:
我正在编写一些代码来自动为元素创建标签。下面是我的代码片段:
doc.Create.NewTag( doc.ActiveView, elem, False, TagMode.TM_ADDBY_CATEGORY, TagOrientation.TAG_HORIZONTAL, panelCenter );
GetElementsOfType:返回指定类型(class)的所有元素;
static FilteredElementCollector GetElementsOfType( Document doc, Type type, BuiltInCategory bic ) { FilteredElementCollector collector = new FilteredElementCollector( doc ); collector.OfCategory( bic ); collector.OfClass( type ); return collector; }GetFamilySymbols:返回指定内置类别(built-in category)的所有族类型;
static FilteredElementCollector GetFamilySymbols( Document doc, BuiltInCategory bic ) { return GetElementsOfType( doc, typeof( FamilySymbol ), bic ); }GetFirstFamilySymbol:返回指定内置类别(built-in category)的第一个族类型;
static FamilySymbol GetFirstFamilySymbol( Document doc, BuiltInCategory bic ) { FamilySymbol s = GetFamilySymbols( doc, bic ) .FirstElement() as FamilySymbol; Debug.Assert( null != s, string.Format( "expected at least one {0} symbol in project", bic.ToString() ) ); return s; }GetBottomAndTopLevels:判定创建墙体的顶层和底层。对一个 empty project 中,顶层和底层分别为 Level 1 和 Level 2;
static bool GetBottomAndTopLevels( Document doc, ref Level levelBottom, ref Level levelTop ) { FilteredElementCollector levels = GetElementsOfType( doc, typeof( Level ), BuiltInCategory.OST_Levels ); foreach( Element e in levels ) { if( null == levelBottom ) { levelBottom = e as Level; } else if( null == levelTop ) { levelTop = e as Level; } else { break; } } if( levelTop.Elevation < levelBottom.Elevation ) { Level tmp = levelTop; levelTop = levelBottom; levelBottom = tmp; } return null != levelBottom && null != levelTop; }有了所有上述的准备工作,下面我就可以 CmdSetTypeTage 命令主体了:
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; Autodesk.Revit.Creation.Application createApp = app.Application.Create; Autodesk.Revit.Creation.Document createDoc = doc.Create; // determine the wall endpoints: double length = 5 * MeterToFeet; XYZ [] pts = new XYZ[2]; pts[0] = XYZ.Zero; pts[1] = new XYZ( length, 0, 0 ); // determine the levels where // the wall will be located: Level levelBottom = null; Level levelTop = null; if( !GetBottomAndTopLevels( doc, ref levelBottom, ref levelTop ) ) { message = "Unable to determine " + "wall bottom and top levels"; return Result.Failed; } // create a wall: BuiltInParameter topLevelParam = BuiltInParameter.WALL_HEIGHT_TYPE; ElementId topLevelId = levelTop.Id; Line line = createApp.NewLineBound( pts[0], pts[1] ); Wall wall = createDoc.NewWall( line, levelBottom, false ); Parameter param = wall.get_Parameter( topLevelParam ); param.Set( topLevelId ); // determine wall thickness for tag // offset and profile growth: double wallThickness = wall.WallType .CompoundStructure.Layers.get_Item( 0 ) .Thickness; // add door to wall; // note that the NewFamilyInstance method // does not automatically add a door tag, // like the ui command does: FamilySymbol doorSymbol = GetFirstFamilySymbol( doc, BuiltInCategory.OST_Doors ); if( null == doorSymbol ) { message = "No door symbol found."; return Result.Failed; } XYZ midpoint = Midpoint( pts[0], pts[1] ); FamilyInstance door = createDoc .NewFamilyInstance( midpoint, doorSymbol, wall, levelBottom, StructuralType.NonStructural ); // create door tag: View view = doc.ActiveView; double tagOffset = 3 * wallThickness; midpoint += tagOffset * XYZ.BasisY; IndependentTag tag = createDoc.NewTag( view, door, false, TagMode.TM_ADDBY_CATEGORY, TagOrientation.TAG_HORIZONTAL, midpoint ); // create and assign new door tag type: FamilySymbol doorTagType = GetFirstFamilySymbol( doc, BuiltInCategory.OST_DoorTags ); doorTagType = doorTagType.Duplicate( "New door tag type" ) as FamilySymbol; tag.ChangeTypeId( doorTagType.Id ); return Result.Succeeded; }该命令在一个 empty project 中运行的结果是:一面墙、一扇门以及指定标签类型的门标签。