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)));
IList wallTypes1 = 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));
IList wallList = 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.
IList doorTypeList = 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.
IList walls = 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 IList FindInstancesOfType(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 IList FindLongWalls()
{
// 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, 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 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 IList FindElements(
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,
Nullable targetCategory)
{
// 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(IList elems, 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 |