15.

Revit API 要素取得|FilteredElementCollector・OfClass・OfCategory・BuiltInCategory・LINQ

編集
Revit API · 15

要素の取得とフィルタ

Revit API で何かをするには、まず「対象の要素を集める」ことから始まります。その中心となるのが FilteredElementCollector。フィルタを連結して、モデルから狙った要素だけを効率よく取り出す方法を学びます。

この記事の要点

  • 要素を取り出す中心クラスは FilteredElementCollector。Document を渡して生成する
  • OfClass(.NET クラスで絞る)と OfCategory(BuiltInCategory で絞る)が代表的なフィルタ
  • WhereElementIsNotElementType でインスタンス、WhereElementIsElementType でタイプを取得できる
  • 結果は IEnumerable なので LINQ(Where / Select / Cast)で柔軟に加工できる

この記事は Revit カテゴリの一部です。API の全体像は Revit API 概要 で押さえておくと理解が早まります。要素を集めたら、編集は トランザクションと要素編集 内で行います。

1FilteredElementCollector の基本

FilteredElementCollector は、Document(またはビュー)を対象に要素を収集するクラスです。生成しただけでは全要素が対象ですが、フィルタを連結(チェーン)して絞り込みます。フィルタは「速い順序」で適用されるよう、まず種別系で絞ってから条件を加えるのが定石です。

パフォーマンスの鍵:遅延評価と早期の絞り込み
コレクタは「遅延評価」で、最終的に列挙(foreach や ToList、ToElements)した時点で初めて実体化します。絞り込みフィルタを連結している途中ではコストがかからず、列挙時にまとめて評価されます。ビューを対象にした new FilteredElementCollector(doc, viewId) なら、そのビューに表示されている要素だけに対象を限定でき、大規模モデルでの高速化に有効です。

2OfClass と OfCategory

絞り込みには 2 系統あります。目的に応じて使い分けます。

OfClass(typeof(Wall)).NET クラス型で絞る
  • Wall、FamilyInstance、ViewPlan などクラスが明確な場合に使う
OfCategory(...)BuiltInCategory で絞る
  • 「ドア」「窓」「部屋」などカテゴリ単位で集めたい場合に使う
  • カテゴリ名は OST_DoorsOST_Rooms のように OST_ 接頭辞が付く

壁インスタンスを取得する基本形は次の通りです。

using Autodesk.Revit.DB;
using System.Collections.Generic;
using System.Linq;

// doc は Document
FilteredElementCollector collector =
    new FilteredElementCollector(doc)
        .OfClass(typeof(Wall))
        .WhereElementIsNotElementType();

List<Wall> walls = collector.Cast<Wall>().ToList();
TaskDialog.Show("結果", "壁の数: " + walls.Count);

List<Wall> のようなジェネリクスを多用するため、型を意識してキャストするのがポイントです。

3インスタンスとタイプの区別

Revit の要素には「タイプ(ElementType: 種類・規格の定義)」と「インスタンス(実際に配置された個体)」があります。コレクタはどちらも拾うため、目的に応じて絞ります。

WhereElementIsNotElementType()
配置済みインスタンスのみ取得。「実際に建っている壁を数える」ような用途
WhereElementIsElementType()
タイプ定義のみ取得。「使用可能な壁タイプを列挙する」ような用途

この絞り込みを忘れると、インスタンスとタイプが混在して件数が想定と合わなくなります。

4ElementId と LINQ による加工

取得した各要素は ElementId で一意に識別されます。ID から本体を得るには doc.GetElement(id) を使い、逆に要素から ID は element.Id で取得できます。

コレクタは IEnumerable<Element> を実装するため、LINQ で柔軟に処理できます。たとえばカテゴリで集めた上で、特定の高さの壁だけを抽出するには次のように書きます。

var tallWalls = new FilteredElementCollector(doc)
    .OfCategory(BuiltInCategory.OST_Walls)
    .WhereElementIsNotElementType()
    .Cast<Wall>()
    .Where(w => w.get_Parameter(
        BuiltInParameter.WALL_USER_HEIGHT_PARAM)
        .AsDouble() > 10.0)   // 内部単位フィート
    .ToList();

LINQ の Where でロジックを表現し、Select で値へ変換、Cast で型を確定する、という流れが基本パターンです。比較する数値は内部単位(フィート)である点に注意してください。

「集める」が API の出発点

Revit API での作業は、ほぼ例外なく「対象要素を集める」ことから始まります。FilteredElementCollector種別系フィルタ → 条件 → LINQ 加工という流れを身につければ、数量集計から一括編集まで応用が利きます。早めの絞り込みでパフォーマンスを保つこと、内部単位がフィートであることの 2 点を忘れないようにしましょう。

要素を集めたら、次は変更です。トランザクションと要素編集 で、安全に値を書き換え・要素を作成する方法を学びましょう。

FilteredElementCollector にフィルタを連鎖して絞り込む 全要素 Document 全体 OfClass .NET クラスで絞る OfCategory BuiltInCategory WhereElementIs NotElementType インスタンスのみ 狙った要素だけが残る 種別系で先に絞ると速い →
図: フィルタの連鎖 — FilteredElementCollector に OfClass → OfCategory → WhereElementIsNotElementType を繋ぐと、Document 全体から狙った要素(配置済みインスタンス)だけが絞り込まれる。種別系を先に適用すると速い。

次に読む

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. Revitとは
  2. ファミリ(システム/ロード/インプレイス)
  3. カテゴリ・タイプ・インスタンス
  4. パラメータ(プロジェクト/共有/グローバル/ファミリ)
  5. レベルと通り芯
  6. ビューとビューテンプレート
  7. シートと図面化
  8. スケジュール表(集計表)
  9. ワークシェアリングと中心ファイル
  10. フェーズとデザインオプション
  11. リンクと座標連携
  12. Dynamo入門
  13. 開発環境構築(Visual Studio + .addin マニフェスト)
  14. Revit API 概要
  15. Revit API:要素の取得とフィルタ
  16. Revit API:トランザクションと要素編集
  17. Revit API:外部コマンド/アプリ

最近更新/作成されたページ