Revit Intro Lab3 - Element Filtering
이번 Lab3 과정도 Lab1,2의 연속적인 프로그램으로 기존에 시작한 프로젝트에 파일을 추가하여 진행하시면 됩니다.
기존의 프로젝트를 오픈하여서 새로운 클래스를 정의할 새로운 파일을 추가한다.
파일명: 3_ElementFiltering.cs 클래스명: ElementFiltering
필요한 네임스페이스
System.Linq
Autodesk.Revit.DB
Autodesk.Revit.UI
Autodesk.Revit.ApplicationServices
Autodesk.Revit.Attributes
Util // 소스파일의 Util.cs파일을 추가 설정하시면 됩니다.
주요변수의 설정
uiApp = commandData.Application
uiDoc = commandData.Application.ActiveUIDocument
_app = commandData.Application.Application
_doc = commandData.Application.ActiveUIDocument.Document
목적 : 이 실습에서는 우리는 어떻게 데이터베이스의 요소를 필터링하는 살펴 보겠습니다.
RVT 프로젝트 데이터베이스의 요소에 액세스하는 주제에 대한 추가 정보에 대해 살펴 보겠습니다.
1. ListFamilyTypes
// 패밀리 유형을 나열
2. ListInstances
// 특정 개체 클래스의 인스턴스를 나열합니다.
3. FindFamilyType
// 특정 패밀리 유형을 찾기
4. FindInstance
// 매개 변수에 의해 필터링을 포함한 특정 인스턴스를 찾기
5. ListAllElements
// 모든 요소를 나열
ListFamilyTypes();
C#소스
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.Attributes; using Util; // 이전과정과 다르게 Util 네임스페이스를 사용합니다. 소스파일에 보시면 Util.cs 파일을 추가하시면 됩니다. // Revit Intro Lab 3 // // In this lab, we'll take a look how to filter element from the database. // 이 실습에서는, 우리는 어떻게 데이터베이스의 요소를 필터링하는 살펴 보겠습니다. // Disclaimer: minimum error checking to focus on the main topic. // 면책 조항 : 주요 주제에 초점을 확인하는 최소한의 오류입니다. namespace IntroCs { /// ElementFiltering // 필터링 요소 [Transaction(TransactionMode.Automatic)] public class ElementFiltering : IExternalCommand { // Member variables // 멤버 변수 Application _app; Document _doc; public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { // Get the access to the top most objects. // 최상위 개체에 액세스 할 수 있습니다. UIApplication uiApp = commandData.Application; UIDocument uiDoc = uiApp.ActiveUIDocument; _app = uiApp.Application; _doc = uiDoc.Document; // (1) In eailer lab, CommandData command, we // learned how to access to the wallType. i.e., // here we'll take a look at more on the topic // of accessing to elements in the interal rvt // project database. // 이전 랩에서 CommandData 명령으로 우리는 wallType에 접근하는 방법을 배웠습니다. // 여기에 우리가 interal RVT 프로젝트 데이터베이스의 요소에 액세스하는 주제에 대한 추가 정보에 대해 살펴 보겠습니다. ListFamilyTypes(); // (2) List instances of specific object class. // 특정 개체 클래스의 인스턴스를 나열합니다. ListInstances(); // (3) Find a specific family type. // 특정 패밀리 유형을 찾을 수 있습니다. FindFamilyType(); // (4) Find specific instances, including filtering by parameters. // 매개 변수에 의해 필터링을 포함한 특정 인스턴스를 찾을 수 있습니다. FindInstance(); // (5) List all elements. // 모든 요소를 ??나열합니다. ListAllElements(); // We are done. // 우리는 할 수 있습니다. return Result.Succeeded; } ////// List the family types // 패밀리 유형을 나열합니다 /// public void ListFamilyTypes() { // (1) Get a list of family types available in the current rvt project. // 현재 RVT 프로젝트에서 사용할 수있는 패밀리 유형의 목록을 가져옵니다. // // For system family types, there is a designated // properties that allows us to directly access to the types. // 시스템 패밀리 유형을 위해, 저희에게 직접 형식에 액세스 할 수 있도록 지정된 속성이 있습니다. // e.g., _doc.WallTypes //WallTypeSet wallTypes = _doc.WallTypes; // 2013 FilteredElementCollector wallTypes = new FilteredElementCollector(_doc) // 2014 .OfClass(typeof(WallType)); int n = wallTypes.Count(); string s = string.Empty; //int n = 0; foreach (WallType wType in wallTypes) { s += "\r\n" + wType.Kind.ToString() + " : " + wType.Name; //++n; } TaskDialog.Show( n.ToString() + " Wall Types:", s ); // (1.1) Same idea applies to other system family, such as Floors, Roofs. // 같은 생각은 바닥, 지붕 등의 다른 시스템 제품군에 적용됩니다. //FloorTypeSet floorTypes = _doc.FloorTypes; FilteredElementCollector floorTypes = new FilteredElementCollector(_doc) // 2014 .OfClass(typeof(FloorType)); s = string.Empty; foreach (FloorType fType in floorTypes) { // Family name is not in the property for // floor, so use BuiltInParameter here. Parameter param = fType.get_Parameter( BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM); if (param != null) { s += param.AsString(); } s += " : " + fType.Name + "\r\n"; } TaskDialog.Show( floorTypes.Count().ToString() + " floor types (by rvtDoc.FloorTypes): ", s); // (1.2a) Another approach is to use a filter. here is an example with wall type. var wallTypeCollector1 = new FilteredElementCollector(_doc); wallTypeCollector1.WherePasses(new ElementClassFilter(typeof(WallType))); IListwallTypes1 = wallTypeCollector1.ToElements(); // Using a helper function to display the result here. See code below. ShowElementList(wallTypes1, "Wall Types (by Filter): "); // (1.2b) The following are the same as two lines above. // These alternative forms are provided for convenience. // Using OfClass() // //FilteredElementCollector wallTypeCollector2 = new FilteredElementCollector(_doc); //wallTypeCollector2.OfClass(typeof(WallType)); // (1.2c) The following are the same as above for convenience. // Using short cut this time. // //FilteredElementCollector wallTypeCollector3 = new FilteredElementCollector(_doc).OfClass(typeof(WallType)); // // (2) Listing for component family types. // // For component family, it is slightly different. // There is no designate property in the document class. // You always need to use a filtering. e.g., for doors and windows. // Remember for component family, you will need to check element type and category. var doorTypeCollector = new FilteredElementCollector(_doc); doorTypeCollector.OfClass(typeof(FamilySymbol)); doorTypeCollector.OfCategory(BuiltInCategory.OST_Doors); IList doorTypes = doorTypeCollector.ToElements(); ShowElementList(doorTypes, "Door Types (by Filter): "); } /// /// To get a list of instances of a specific family type, you will need to use filters. /// The same idea that we learned for family types applies for instances as well. /// public void ListInstances() { // List all the wall instances var wallCollector = new FilteredElementCollector(_doc).OfClass(typeof(Wall)); IListwallList = wallCollector.ToElements(); ShowElementList(wallList, "Wall Instances: "); // List all the door instances var doorCollector = new FilteredElementCollector(_doc).OfClass(typeof(FamilyInstance)); doorCollector.OfCategory(BuiltInCategory.OST_Doors); IList doorList = doorCollector.ToElements(); ShowElementList(doorList, "Door Instance: "); } /// /// Looks at a way to get to the more specific family types with a given name. /// public void FindFamilyType() { // In this exercise, we will look for the following family types for wall and door // Hard coding for similicity. modify here if you want to try out with other family types. // Constant to this function. // This is for wall. e.g., "Basic Wall: Generic - 200mm" const string wallFamilyName = Util.Constant.WallFamilyName; const string wallTypeName = Util.Constant.WallTypeName; const string wallFamilyAndTypeName = wallFamilyName + ": " + wallTypeName; // This is for door. e.g., "M_Single-Flush: 0915 x 2134mm const string doorFamilyName = Util.Constant.DoorFamilyName; const string doorTypeName = Util.Constant.DoorTypeName; const string doorFamilyAndTypeName = doorFamilyName + ": " + doorTypeName; // Keep messages to the user in this function. string msg = "Find Family Type - All:\r\n\r\n"; // (1) Get a specific system family type. e.g., wall type. // There are a few different ways to do this. // (1.1) First version uses LINQ query. ElementType wallType1 = (ElementType)FindFamilyType_Wall_v1(wallFamilyName, wallTypeName); // Show the result. msg += ShowFamilyTypeAndId("Find wall family type (using LINQ): ", wallFamilyAndTypeName, wallType1) + "\r\n"; // (1.2) Another way is to use iterator. (cf. look for example, Developer guide 87) ElementType wallType2 = (ElementType)FindFamilyType_Wall_v2(wallFamilyName, wallTypeName); msg += ShowFamilyTypeAndId("Find wall family type (using iterator): ", wallFamilyAndTypeName, wallType2) + "\r\n"; // (1.3) The most efficient method is to use a parameter filter, since // this avoids mashalling and transporting all the data for the rejected // results from the internal Revit memory to the external .NET space: ElementType wallType3 = FindFamilyType_Wall_v3( wallFamilyName, wallTypeName) as ElementType; msg += ShowFamilyTypeAndId("Find wall family type (using parameter filter): ", wallFamilyAndTypeName, wallType2) + "\r\n"; // (2) Get a specific component family type. e.g., door type. // // (2.1) Similar approach as (1.1) using LINQ. ElementType doorType1 = (ElementType)FindFamilyType_Door_v1(doorFamilyName, doorTypeName); msg += ShowFamilyTypeAndId("Find door type (using LINQ): ", doorFamilyAndTypeName, doorType1) + "\r\n"; // (2.2) Get a specific door type. The second approach. // Another approach will be to look up from Family, then from Family.Symbols property. // This gets more complicated although it is logical approach. ElementType doorType2 = (ElementType)FindFamilyType_Door_v2(doorFamilyName, doorTypeName); msg += ShowFamilyTypeAndId("Find door type (using Family): ", doorFamilyAndTypeName, doorType2) + "\r\n"; // (3) Here is more generic form. defining a more generalized function below. // // (3.1) For the wall type ElementType wallType4 = (ElementType)FindFamilyType(_doc, typeof(WallType), wallFamilyName, wallTypeName, null); msg += ShowFamilyTypeAndId("Find wall type (using generic function): ", wallFamilyAndTypeName, wallType4) + "\r\n"; // (3.2) For the door type. ElementType doorType3 = (ElementType)FindFamilyType(_doc, typeof(FamilySymbol), doorFamilyName, doorTypeName, BuiltInCategory.OST_Doors); msg += ShowFamilyTypeAndId("Find door type (using generic function): ", doorFamilyAndTypeName, doorType3) + "\r\n"; // (3.3) Simply return the first wall and door type encountered, so we do // not have to worry about setting up its family and symbol name // correctly: ElementType wallType5 = new FilteredElementCollector(_doc) .WhereElementIsElementType() // superfluous, because WallType is derived from ElementType .OfClass(typeof(WallType)) .OfCategory(BuiltInCategory.OST_Walls) // superfluous, because al WallType instances have this category .FirstElement() as ElementType; msg += ShowFamilyTypeAndId("Find first wall type (using generic function): ", wallType5.Name, wallType5) + "\r\n"; ElementType doorType4 = GetFirstFamilySymbol(_doc, BuiltInCategory.OST_Doors) as ElementType; msg += ShowFamilyTypeAndId("Find first door type (using generic function): ", doorType4.Name, doorType4) + "\r\n"; // Finally, show the result all together TaskDialog.Show("Find family types", msg); } ////// Find a specific family type for a wall with a given family and type names. /// This version uses LINQ query. /// public Element FindFamilyType_Wall_v1(string wallFamilyName, string wallTypeName) { // Narrow down a collector with class. var wallTypeCollector1 = new FilteredElementCollector(_doc); wallTypeCollector1.OfClass(typeof(WallType)); // LINQ query var wallTypeElems1 = from element in wallTypeCollector1 where element.Name.Equals(wallTypeName) select element; // Get the result. Element wallType1 = null; // Result will go here. // (1) Directly accessing from the query result. if (wallTypeElems1.Count() > 0) { wallType1 = wallTypeElems1.First (); } // (2) If you want to get the result as a list of element, here is how. //IList wallTypeList1 = wallTypeElems1.ToList(); //if (wallTypeList1.Count > 0) // wallType1 = wallTypeList1[0]; // Found it. return wallType1; } /// /// Find a specific family type for a wall, which is a system family. /// This version uses iteration. (cf. look for example, Developer guide 87) /// public Element FindFamilyType_Wall_v2(string wallFamilyName, string wallTypeName) { // First, narrow down the collector by Class var wallTypeCollector2 = new FilteredElementCollector(_doc).OfClass(typeof(WallType)); // Use iterator FilteredElementIterator wallTypeItr = wallTypeCollector2.GetElementIterator(); wallTypeItr.Reset(); Element wallType2 = null; while (wallTypeItr.MoveNext()) { WallType wType = (WallType)wallTypeItr.Current; // We check two names for the match: type name and family name. if ((wType.Name == wallTypeName) & (wType.get_Parameter(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM).AsString().Equals(wallFamilyName))) { wallType2 = wType; // We found it. break; } } return wallType2; } ////// Find a specific family type for a wall, which is a system family. /// Most efficient way to find a named family symbol: use a parameter filter. /// public Element FindFamilyType_Wall_v3( string wallFamilyName, string wallTypeName) { ParameterValueProvider provider = new ParameterValueProvider( new ElementId(BuiltInParameter.DATUM_TEXT)); FilterStringRuleEvaluator evaluator = new FilterStringEquals(); FilterRule rule = new FilterStringRule( provider, evaluator, wallTypeName, true); ElementParameterFilter filter = new ElementParameterFilter(rule); return new FilteredElementCollector(_doc) .OfClass(typeof(WallType)) .WherePasses(filter) .FirstElement(); } ////// Find a specific family type for a door, which is a component family. /// This version uses LINQ. /// public Element FindFamilyType_Door_v1(string doorFamilyName, string doorTypeName) { // narrow down the collection with class and category. var doorFamilyCollector1 = new FilteredElementCollector(_doc); doorFamilyCollector1.OfClass(typeof(FamilySymbol)); doorFamilyCollector1.OfCategory(BuiltInCategory.OST_Doors); // Parse the collection for the given name // Using LINQ query here. var doorTypeElems = from element in doorFamilyCollector1 where element.Name.Equals(doorTypeName) && element.get_Parameter(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM).AsString().Equals(doorFamilyName) select element; // Get the result. Element doorType1 = null; // (1) Directly accessing from the query result //if (doorTypeElems.Count > 0) // we should have only one with the given name. minimum error checking. // doorType1 = doorTypeElems[0]; // found it. // (2) If we want to get the list of element, here is how. IListdoorTypeList = doorTypeElems.ToList(); if (doorTypeList.Count > 0) { // We should have only one with the given name. minimum error checking. doorType1 = doorTypeList[0]; // Found it. } return doorType1; } /// /// Find a specific family type for a door. /// another approach will be to look up from Family, then from Family.Symbols property. /// This gets more complicated although it is logical approach. /// public Element FindFamilyType_Door_v2(string doorFamilyName, string doorTypeName) { // (1) find the family with the given name. var familyCollector = new FilteredElementCollector(_doc); familyCollector.OfClass(typeof(Family)); // Use the iterator Family doorFamily = null; FilteredElementIterator familyItr = familyCollector.GetElementIterator(); //familyItr.Reset(); while ((familyItr.MoveNext())) { Family fam = (Family)familyItr.Current; // Check name and categoty if ((fam.Name == doorFamilyName) & (fam.FamilyCategory.Id.IntegerValue == (int)BuiltInCategory.OST_Doors)) { // We found the family. doorFamily = fam; break; } } // (2) Find the type with the given name. Element doorType2 = null; // Id of door type we are looking for. if (doorFamily != null) { // If we have a family, then proceed with finding a type under Symbols property. FamilySymbolSet doorFamilySymbolSet = doorFamily.Symbols; // Iterate through the set of family symbols. FamilySymbolSetIterator doorTypeItr = doorFamilySymbolSet.ForwardIterator(); while (doorTypeItr.MoveNext()) { FamilySymbol dType = (FamilySymbol)doorTypeItr.Current; if ((dType.Name == doorTypeName)) { doorType2 = dType; // Found it. break; } } } return doorType2; } ////// Find specific instances, including filtering by parameters. /// public void FindInstance() { // Constant to this function. (we may want to change the value here.) // This is for wall. e.g., "Basic Wall: Generic - 200mm" const string wallFamilyName = Util.Constant.WallFamilyName; const string wallTypeName = Util.Constant.WallTypeName; // Util.Constant.WallTypeName const string wallFamilyAndTypeName = wallFamilyName + ": " + wallTypeName; // This is for door. e.g., "M_Single-Flush: 0915 x 2134mm const string doorFamilyName = Util.Constant.DoorFamilyName; const string doorTypeName = Util.Constant.DoorTypeName; const string doorFamilyAndTypeName = doorFamilyName + ": " + doorTypeName; // (1) Find walls with a specific type // // Find a specific family type. use the function we defined earlier. ElementId idWallType = FindFamilyType(_doc, typeof(WallType), wallFamilyName, wallTypeName, null).Id; // Find instances of the given family type. IListwalls = FindInstancesOfType(typeof(Wall), idWallType, null); // Show it. string msgWalls = "Instances of wall with type: " + wallFamilyAndTypeName + "\r\n"; ShowElementList(walls, msgWalls); // (2) Find a specific door. same idea. ElementId idDoorType = FindFamilyType(_doc, typeof(FamilySymbol), doorFamilyName, doorTypeName, BuiltInCategory.OST_Doors).Id; // error in elementfiltering IList doors = FindInstancesOfType(typeof(FamilyInstance), idDoorType, BuiltInCategory.OST_Doors); string msgDoors = "Instances of door with type: " + doorFamilyAndTypeName + "\r\n"; ShowElementList(doors, msgDoors); // (3) Apply the same idea to the supporting element, such as level. // In this case, we simply check the name. // This becomes handy when you are creating an object on a certain level, // for example, when we create a wall. // We will use this in the lab 5 when we create a simple house. Level level1 = (Level)FindElement(_doc, typeof(Level), "Level 1", null); string msgLevel1 = "Level1: " + "\r\n" + ElementToString(level1) + "\r\n"; TaskDialog.Show("Find instance", msgLevel1); // (4) Finally, let's see how to use parameter filter // Let's try to get a wall whose length is larger than 60 feet. IList longWalls = FindLongWalls(); string msgLongWalls = "Long walls: " + "\r\n"; ShowElementList(longWalls, msgLongWalls); } /// /// Helper function: find a list of element with given class, family type and category (optional). /// public IListFindInstancesOfType(Type targetType, ElementId idType, Nullable targetCategory) { // First, narrow down to the elements of the given type and category var collector = new FilteredElementCollector(_doc).OfClass(targetType); if (targetCategory.HasValue) { collector.OfCategory(targetCategory.Value); } // Parse the collection for the given family type id. // Using LINQ query here. var elems = from element in collector where element.get_Parameter(BuiltInParameter.SYMBOL_ID_PARAM).AsElementId().Equals(idType) select element; // Put the result as a list of element fo accessibility. return elems.ToList(); } /// /// Optional - example of parameter filter. /// Find walls whose length is longer than a certain length. e.g., 60 feet /// wall.parameter(length) > 60 feet /// This could get more complex than looping through in terms of writing a code. /// See page 87 of Developer guide. /// public IListFindLongWalls() { // Constant for this function. const double kWallLength = 60.0; // 60 feet. hard coding for simplicity. // First, narrow down to the elements of the given type and category var collector = new FilteredElementCollector(_doc).OfClass(typeof(Wall)); // Define a filter by parameter // 1st arg - value provider BuiltInParameter lengthParam = BuiltInParameter.CURVE_ELEM_LENGTH; int iLengthParam = (int)lengthParam; var paramValueProvider = new ParameterValueProvider(new ElementId(iLengthParam)); // 2nd - evaluator FilterNumericGreater evaluator = new FilterNumericGreater(); // 3rd - rule value double ruleVal = kWallLength; // 4th - epsilon const double eps = 1E-06; // Define a rule var filterRule = new FilterDoubleRule(paramValueProvider, evaluator, ruleVal, eps); // Create a new filter var paramFilter = new ElementParameterFilter(filterRule); // Go through the filter IList elems = collector.WherePasses(paramFilter).ToElements(); return elems; } /// /// List all elements in Revit database. /// void ListAllElements() { // Create an output file: string filename = Path.Combine( Path.GetTempPath(), "RevitElements.txt"); StreamWriter sw = new StreamWriter(filename); // The Revit API does not expect an application // ever to need to iterate over all elements. // To do so, we need to use a trick: ask for all // elements fulfilling a specific criteria and // unite them with all elements NOT fulfilling // the same criteria; an arbitrary criterion // could be chosen: FilteredElementCollector collector = new FilteredElementCollector(_doc) .WhereElementIsElementType(); FilteredElementCollector collector2 = new FilteredElementCollector(_doc) .WhereElementIsNotElementType(); collector.UnionWith(collector2); // Loop over the elements and list their data: string s, line; foreach (Element e in collector) { line = "Id=" + e.Id.IntegerValue.ToString(); // element id line += "; Class=" + e.GetType().Name; // element class, i.e. System.Type // The element category is not implemented for all classes, // and may return null; for family elements, one can sometimes // use the FamilyCategory property instead. s = string.Empty; if (null != e.Category) { s = e.Category.Name; } if (0 == s.Length && e is Family && null != ((Family)e).FamilyCategory) { s = ((Family)e).FamilyCategory.Name; } if (0 == s.Length) { s = "?"; } line += "; Category=" + s; // The element Name property has a different meaning for different classes, // but is mostly implemented 'logically'. More precise info on elements // can be obtained in class-specific ways. line += "; Name=" + e.Name; //line += "; UniqueId=" + e.UniqueId; //line += "; Guid=" + GetGuid( e.UniqueId ); sw.WriteLine(line); } sw.Close(); TaskDialog.Show("List all elements", string.Format("Element list has been written to '{0}'.", filename)); } #region Helper Functions //==================================================================== // Helper Functions //==================================================================== ////// Helper function: find an element of the given type, name, and category(optional) /// You can use this, for example, to find a specific wall and window family with the given name. /// e.g., /// FindFamilyType(_doc, GetType(WallType), "Basic Wall", "Generic - 200mm") /// FindFamilyType(_doc, GetType(FamilySymbol), "M_Single-Flush", "0915 x 2134mm", BuiltInCategory.OST_Doors) /// public static Element FindFamilyType(Document rvtDoc, Type targetType, string targetFamilyName, string targetTypeName, NullabletargetCategory) { // First, narrow down to the elements of the given type and category var collector = new FilteredElementCollector(rvtDoc).OfClass(targetType); if (targetCategory.HasValue) { collector.OfCategory(targetCategory.Value); } // Parse the collection for the given names // Using LINQ query here. var targetElems = from element in collector where element.Name.Equals(targetTypeName) && element.get_Parameter(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM). AsString().Equals(targetFamilyName) select element; // Put the result as a list of element fo accessibility. IList elems = targetElems.ToList(); // Return the result. if (elems.Count > 0) { return elems[0]; } return null; } /// /// Return all elements of the requested class, /// i.e. System.Type, matching the given built-in /// category in the given document. /// public static FilteredElementCollector GetElementsOfType( Document doc, Type type, BuiltInCategory bic) { FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfCategory(bic); collector.OfClass(type); return collector; } ////// Return all family symbols in the given document /// matching the given built-in category. /// Todo: Compare this with the FamilySymbolFilter class. /// public static FilteredElementCollector GetFamilySymbols( Document doc, BuiltInCategory bic) { return GetElementsOfType(doc, typeof(FamilySymbol), bic); } ////// Return the first family symbol found in the given document /// matching the given built-in category or null if none is found. /// public 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; } ////// Helper function: find a list of element with given Class, Name and Category (optional). /// public static IListFindElements( Document rvtDoc, Type targetType, string targetName, Nullable targetCategory) { // First, narrow down to the elements of the given type and category var collector = new FilteredElementCollector(rvtDoc).OfClass(targetType); if (targetCategory.HasValue) { collector.OfCategory(targetCategory.Value); } // Parse the collection for the given names // Using LINQ query here. var elems = from element in collector where element.Name.Equals(targetName) select element; // Put the result as a list of element for accessibility. return elems.ToList(); } /// /// Helper function: searches elements with given Class, Name and Category (optional), /// and returns the first in the elements found. /// This gets handy when trying to find, for example, Level. /// e.g., FindElement(_doc, GetType(Level), "Level 1") /// public static Element FindElement( Document rvtDoc, Type targetType, string targetName, NullabletargetCategory) { // Find a list of elements using the overloaded method. IList elems = FindElements(rvtDoc, targetType, targetName, targetCategory); // Return the first one from the result. if (elems.Count > 0) { return elems[0]; } return null; } /// /// Helper function: to show the result of finding a family type. /// public string ShowFamilyTypeAndId(string header, string familyAndTypeName, ElementType familyType) { // Show the result. string msg = header + "\r\n" + familyAndTypeName + " >> Id = "; if (familyType != null) { msg += familyType.Id.ToString() + "\r\n"; } // Uncomment this if you want to show each result. //TaskDialog.Show( "Show family type and id", msg ); return msg; } ////// Helper function to display info from a list of elements passed onto. /// public void ShowElementList(IListelems, string header) { string s = " - Class - Category - Name (or Family: Type Name) - Id - \r\n"; foreach (Element e in elems) { s += ElementToString(e); } TaskDialog.Show(header + "(" + elems.Count.ToString() + "):", s); } /// /// Helper function: summarize an element information as a line of text, /// which is composed of: class, category, name and id. /// name will be "Family: Type" if a given element is ElementType. /// Intended for quick viewing of list of element, for example. /// public string ElementToString(Element e) { if (e == null) { return "none"; } string name = ""; if (e is ElementType) { Parameter param = e.get_Parameter(BuiltInParameter.SYMBOL_FAMILY_AND_TYPE_NAMES_PARAM); if (param != null) { name = param.AsString(); } } else { name = e.Name; } return e.GetType().Name + "; " + e.Category.Name + "; " + name + "; " + e.Id.IntegerValue.ToString() + "\r\n"; } #endregion } }
'Revit > Revit API' 카테고리의 다른 글
[레빗 API 시작하기] Revit Intro Lab5 - ModelCreation (0) | 2013.12.05 |
---|---|
[레빗 API 시작하기] Revit Intro Lab4 - Element Modification (0) | 2013.12.05 |
[레빗 API 시작하기] Lab2-DbElement (0) | 2013.10.31 |
C# 시작하기 (0) | 2013.10.19 |
[레빗 API 시작하기] Lab1-HelloWorld (0) | 2013.10.13 |