フィルタされた要素または要素 ID を取得する

フィルタされた要素または要素 ID を取得する

FilteredElementCollector に 1 つまたは複数のフィルタを適用した後、次の 3 つの方法のいずれかを使用してフィルタされた要素のセットを取得することができます。

  1. 要素または ElementIds のコレクションを取得します。
    • ToElements() - 適用したすべてのフィルタを通過するすべての要素を返します
    • ToElementIds() - 適用したすべてのフィルタを通過するすべての要素の ElementIds を返します
  2. フィルタに一致する最初の要素または ElementId を取得します。
    • FirstElement() - 適用したすべてのフィルタを通過する最初の要素を返します
    • FirstElementId() - 適用したすべてのフィルタを通過する最初の要素の ID を返します
  3. ElementId または要素のイテレタを取得します。
    • GetElementIdIterator() - フィルタを通過する要素 ID へ FilteredElementIdIterator を返します
    • GetElementIterator() - フィルタを通過する要素へ FilteredElementIterator を返します
    • GetEnumerator() - 通過した要素のコレクション内で反復する IEnumerator<Element> を返します。

これらのグループのメソッドを使用する場合は一度に 1 つのみにする必要があります。要素を抽出する別のメソッドを呼び出すと、コレクタによってリセットされてしまいます。つまり、既にイテレタを取得している場合は、要素を抽出するための別のメソッドを呼び出すには、走査を停止して要素を移動させないようにします。

最適なメソッドはアプリケーションによって異なります。一致する要素が 1 つだけ必要な場合は、FirstElement()か FirstElementId()が最適です。一致するすべての要素が必要な場合は、ToElements()を使用します。イテレタ変数が必要な場合は、イテレータを使用します。

アプリケーションが要素を削除したり、フィルタされた要素のリスト内の要素に大幅な変更を行う場合は、ToElementIds()や要素 ID イテレタが最適ですこれは、要素を削除したり、要素に大幅な変更を行うと、要素処理が無効になる場合があるためです。要素 ID を使用して、ElementId とともに Document.GetElement()を呼び出すと、常に有効な要素が返されます(要素が削除されている場合は、null 参照が返されます)。

要素のコレクションとしてフィルタ結果を取得するために ToElements()メソッドを使用すると、下に示すように foreach を使用してセット内の各要素を検証することができます。

コード領域 6-9: ToElements()を使用してフィルタ結果を取得

// Use ElementClassFilter to find all loads in the document
// Using typeof(LoadBase) will yield all AreaLoad, LineLoad and PointLoad
ElementClassFilter filter = new ElementClassFilter(typeof(LoadBase));

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.WherePasses(filter);
ICollection<Element> allLoads = collector.ToElements();

String prompt = "The loads in the current document are:\n";
foreach (Element loadElem in allLoads)
{
        LoadBase load = loadElem as LoadBase;
        prompt += load.GetType().Name +  ": " + 
                        load.Name + "\n";
}

TaskDialog.Show("Revit", prompt);

通過した要素が 1 つだけ必要な場合は、FirstElement()を使用します。

コード領域 6-10: 最初に通過した要素を取得

// Create a filter to find all columns
StructuralInstanceUsageFilter columnFilter = 
        new StructuralInstanceUsageFilter(StructuralInstanceUsage.Column);

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.WherePasses(columnFilter);

// Get the first column from the filtered results
// Element will be a FamilyInstance
FamilyInstance column = collector.FirstElement() as FamilyInstance;

場合によっては、FirstElement()では不十分です。次の例は、拡張メソッドを使用して、最初のテンプレート以外の 3D ビューを取得する方法を表しています(ReferenceIntersector コンストラクタへの入力に便利です)。

コード領域 6-11: 拡張メソッドを使用して最初に通過した要素を取得

// Use filter to find a non-template 3D view
// This example does not use FirstElement() since first filterd view3D might be a template
FilteredElementCollector collector = new FilteredElementCollector(document);
Func<View3D, bool> isNotTemplate = v3 => !(v3.IsTemplate);

// apply ElementClassFilter
collector.OfClass(typeof(View3D));

// use extension methods to get first non-template View3D
View3D view3D = collector.Cast<View3D>().First<View3D>(isNotTemplate);

次の例は、FirstElementId()メソッドを使用して通過した要素(この場合は 3D ビュー)を 1 つ取得する方法および、ToElementIds()メソッドを使用して要素 ID のコレクションとしてフィルタ結果を取得する方法(この場合は、一連の要素を削除するため)を表しています。

コード領域 6-12: 要素 ID としてフィルタ結果を取得

FilteredElementCollector collector = new FilteredElementCollector(document);

// Use shortcut OfClass to get View elements
collector.OfClass(typeof(View3D));

// Get the Id of the first view
ElementId viewId = collector.FirstElementId();

// Test if the view is valid for element filtering
if (FilteredElementCollector.IsViewValidForElementIteration(document, viewId))
{
        FilteredElementCollector viewCollector = new FilteredElementCollector(document, viewId);

        // Get all FamilyInstance items in the view
        viewCollector.OfClass(typeof(FamilyInstance));
        ICollection<ElementId> familyInstanceIds = viewCollector.ToElementIds();

        document.Delete(familyInstanceIds);
}

フィルタされた要素を反復して一部の配管の流れの状態を確認する次の例では、GetElementIterator()メソッドを使用します。

コード領域 6-13: 要素イテレタとして結果を取得

FilteredElementCollector collector = new FilteredElementCollector(document);

// Apply a filter to get all pipes in the document
collector.OfClass(typeof(Autodesk.Revit.DB.Plumbing.Pipe));

// Get results as an element iterator and look for a pipe with
// a specific flow state
FilteredElementIterator elemItr = collector.GetElementIterator();
elemItr.Reset();
while (elemItr.MoveNext())
{
        Pipe pipe = elemItr.Current as Pipe;
        if (pipe.FlowState == PipeFlowState.LaminarState)
        {
                TaskDialog.Show("Revit", "Model has at least one pipe with Laminar flow state.");
                break;
        }
}

また、フィルタ結果を要素 ID イテレタとして返すこともできます。

コード領域 6-14: 要素 ID イテレタとして結果を取得

// Use a RoomFilter to find all room elements in the document. 
RoomFilter filter = new RoomFilter();

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.WherePasses(filter);

// Get results as ElementId iterator
FilteredElementIdIterator roomIdItr = collector.GetElementIdIterator();
roomIdItr.Reset();
while (roomIdItr.MoveNext())
{
        ElementId roomId = roomIdItr.Current;
        // Warn rooms smaller than 50 SF
        Room room = document.GetElement(roomId) as Room;
        if (room.Area < 50.0)
        {
                String prompt = "Room is too small: id = " + roomId.ToString();
                TaskDialog.Show("Revit", prompt);
                break;
        }
}
場合によっては、フィルタを通過するすべての要素を取得するのではなく、特定のフィルタに対して単一の要素をテストする方が便利な場合があります。特定の要素や ElementId をフィルタに対してテストする ElementFilter.PassesFilter()には 2 つのオーバーロードがあり、要素がフィルタを通過した後 True を返します。