Revitアドインでレベルを自動作成 #006

Revitのモデリングで最初にやることはレベル(階)を設定することです。一度作業すれば済むことですのでアドインで行ってもそんなに効率化にはなりません。しかし、こういったこともプログラミングでできることをご紹介します。

Revitの最初の状態

これはRevit2024に付いている建設テンプレートでモデリングを開始したときです。初期値としてレベル 2までできています。

いよいよレベル作成のアドイン

Formの作成

レベル作成に際してはどういう名前で、どの高さに設定するかのUIが必要です。ここではWindows Formを作ります。フォームの左半分には既存で設定されているレベルの情報を表示し、右半分には追加で新規作成するレベルを入力きるようにします。これらのパーツはDataGridViewです。

なおこのようなUIの別案としてはExcelファイルに記入してもらいそれを読み込む方法もあるでしょう。

Form1.csのコードはこんなふうになります。BindingListを利用してDataGridViewにデータバインディングし、UI⇔データの相互連携を可能にしています。Listを使った場合には片方向データバインド(UI → データ)になります。

ボタンのプロパティでOKボタンにはDialogResult.OKを、CancelボタンにはDialogResult.Cancelを設定しておきます。

 public partial class Form1 : Form
 {
     //既存レベル
     public BindingList<LevelClass> exsistLevels;
     //新規レベル
     public BindingList<LevelClass> newLevels;
     public Form1()
     {
         InitializeComponent();

         newLevels = new BindingList<LevelClass>();
         exsistLevels = new BindingList<LevelClass>();
         //既存レベル
         dataGridView1.DataSource = exsistLevels;
         //新規レベル
         dataGridView2.DataSource = newLevels;
     }

     private void button1_Click(object sender, EventArgs e)
     {
         this.Close();
     }

     private void button2_Click(object sender, EventArgs e)
     {
         this.Close();
     }
 }

LevelClass.csはレベル情報を保持するためのシンプルなクラスです

public class LevelClass
{
    public string LevelName { get; set; }
    public double LevelHeight { get; set; }
}

アドイン本体Command.cs

Command.csは次のとおり。

public class Command : IExternalCommand
{
    public Result Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements)
    {
        UIApplication uiapp = commandData.Application;
        UIDocument uidoc = uiapp.ActiveUIDocument;
        Application app = uiapp.Application;
        Document doc = uidoc.Document;
        View view = doc.ActiveView;

        // FilteredElementCollectorでレベルを全部取得する
        List<Level> levels = new FilteredElementCollector(doc)
            .OfClass(typeof(Level))
            .OfCategory(BuiltInCategory.OST_Levels)
            .Cast<Level>()
            .ToList();
        //レベルを高い順にソート(見た目のため)
        levels.Sort((a, b) => b.Elevation.CompareTo(a.Elevation));
        //フォーム作成
        Form1 form1 = new Form1();
        //既設レベルから LevelClassクラスのインスタンスを作ってデータバインディングのexsistLevelsに追加
        List<string> levelStrings = new List<string>();
        foreach (var level in levels)
        {
            //小数点以下0桁で四捨五入表示
            double levelHeightDigit = Math.Round(Conv2(level.Elevation), 0, MidpointRounding.AwayFromZero);
            LevelClass levelClass = new LevelClass() { LevelName = $"{level.Name}", LevelHeight = levelHeightDigit };
            form1.exsistLevels.Add(levelClass);
        }
        //フォーム表示
        form1.ShowDialog();
        //OKボタンが押された場合
        if (form1.DialogResult == System.Windows.Forms.DialogResult.OK)
        {
            using (Transaction tx = new Transaction(doc))
            {
                tx.Start("Create Levels");
                //データバインディングのnewLevelsからLevelClassクラスのインスタンスを作って新規レベルを作成
                foreach (LevelClass lebelClass in form1.newLevels)
                {
                    //新規レベルの名前
                    string levelName = lebelClass.LevelName;
                    //新規レベルの高さ
                    double levelHeight = Conv(lebelClass.LevelHeight);
                    //レベルを作成する
                    Level newLevelElement = Level.Create(doc, levelHeight);
                    newLevelElement.Name = levelName;
                }
                tx.Commit();
            }
        }
        else if (form1.DialogResult == System.Windows.Forms.DialogResult.Cancel)
        {
            //キャンセルボタンが押された場合
            return Result.Cancelled;
        }
        return Result.Succeeded;
    }
    //ミリメートル単位を内部単位に変換
    private static double Conv(double mm)
    {
        return UnitUtils.ConvertToInternalUnits(mm, UnitTypeId.Millimeters);
    }
    //内部単位をミリメートル単位に変換
    private static double Conv2(double mm)
    {
        return UnitUtils.ConvertFromInternalUnits(mm, UnitTypeId.Millimeters);
    }
}

既存のレベルの取得と表示

部分的に見て解説します。

次の部分は既存のレベルを全部取得しています。フォームに表示するときに上のレベルが上に表示されるようにソートしています。

// FilteredElementCollectorでレベルを全部取得する
List<Level> levels = new FilteredElementCollector(doc)
    .OfClass(typeof(Level))
    .OfCategory(BuiltInCategory.OST_Levels)
    .Cast<Level>()
    .ToList();
//レベルを高い順にソート(見た目のため)
levels.Sort((a, b) => b.Elevation.CompareTo(a.Elevation));

既存のレベルをForm1に表示します

//フォーム作成
Form1 form1 = new Form1();
//既設レベルから LevelClassクラスのインスタンスを作ってデータバインディングのexsistLevelsに追加
foreach (var level in levels)
{
    //小数点以下0桁で四捨五入表示
    double levelHeightDigit = Math.Round(Conv2(level.Elevation), 0, MidpointRounding.AwayFromZero);
    LevelClass levelClass = new LevelClass() { LevelName = $"{level.Name}", LevelHeight = levelHeightDigit };
    form1.exsistLevels.Add(levelClass);
}
//フォーム表示
form1.ShowDialog();

ここで表示されるForm1はこんな感じです

新規のレベルの入力

ユーザーは右半分に新規で作成したいレベルを入力します

新規のレベル作成

表示されたForm1にユーザーが新規レベルを入力したあとにOKボタンを押すと次のコード部分が実行されてレベルが作成されます。レベルを作成するところはLevel.Create()です。

//OKボタンが押された場合
if (form1.DialogResult == System.Windows.Forms.DialogResult.OK)
{
    using (Transaction tx = new Transaction(doc))
    {
       tx.Start("Create Levels");
       //データバインディングのnewLevelsからLevelClassクラスのインスタンスを作って新規レベルを作成
       foreach (LevelClass lebelClass in form1.newLevels)
       {
           //新規レベルの名前
           string levelName = lebelClass.LevelName;
           //新規レベルの高さ
           double levelHeight = Conv(lebelClass.LevelHeight);
           //レベルを作成する
           Level newLevelElement = Level.Create(doc, levelHeight);
           newLevelElement.Name = levelName;
       }
       tx.Commit();

作成されたレベルは次のようにレベル 3から5が追加されます

ビューのほうは自動的に追加されません。手動で作成することになります。(ビューも後日、自動で作成する方法を説明します)

なお手動でレベル 6を追加してみると自動的にビューができます

まとめ

レベルの自動作成は意外に簡単です。UIを使いやすく作るとよいと思います。この例では既存のレベルの高さ変更や名前変更はできませんが、改造すれば可能です。

コード全体はgithubを参照してください。

https://github.com/katsumikawasaki/RevitAddinCreateLevels.git

(ご注意)ここに掲載したコードはひとつの技術的な解法を示すサンプルです。実践的な用途に耐えうる堅牢性や品質等は備えていません。コードの実行結果について当組織は一切責任を負いませんので、参照、利用はご自身の責任でお願いします。

書籍もぜひご覧ください


コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です