Revit Project Dashboard with pyRevit and Streamlit

4 min read読了の目安(約4300字

1. pyRevitとは

pyRevitは、Autodesk Revit®のラピッド・アプリケーション・デベロップメント (RAD) 環境です。Revit 環境とその API を使用して、使い慣れた言語で、自動化やアドオンのアイデアを素早くスケッチすることができます。また、開発環境としての使用例を示す豊富で強力なツールのセットが付属しています。pyRevitをダウンロードしてインストールすることで、Revitを起動し、新しく表示されるpyRevitタブおよび含まれるツールも参考にしてください!!

インストール方法はこちら

2. Streamlitとは

StreamlitはPythonを使って数分でデータ表示をすることができる共有可能なWebアプリケーションを作ることができます。
以下のコマンドを実行することでインストールすることができます。
使用可能なPythonのバージョンは3.6-3.8となります。

pip install streamlit
streamlit hello

3. pyRevit Routeとは

ウェブアプリケーションは2つの部分に分割されます。

  • フロントエンド: ブラウザで動作し、ユーザーインターフェースとして動作する部分
  • バックエンド:フロントエンドがデータを送受信するために接触する部分
    フロントエンドを今回はStreamlitで担います。しかし、Revitデータにアクセスして Revit ドキュメントを操作、修正したりできるバックエンドをどのように作成するかという課題が常にありました。pyRevit Routeを用いることでバックエンドの問題を解決することができます。

4. pyRevit Route Extensionの使い方

pyRevit側のフォルダ構成

まずはpyRevitのExtensionと指定しているディレクトリ(フォルダ)の直下にRoute用のフォルダを作成します。作成後作製したディレクトリの直下にstartup.pyというファイルを作成すると完了です。

pyRevit-Sample-Extensions/
    |----pyRevitRoute.Extension/
        |----startup.py

5. Streamlitでプロジェクトタイトルを表示する

5.1 pyRevit側

まずは、Startupファイルでプロジェクトタイトルを取得します。

doc = __revit__.ActiveUIDocument.Document
title = doc.Title

このデータを送る場所を決めます。今回はroute-sampleの中に/titleを作ってデータを送ってみましょう!!

from pyrevit import routes

api = routes.API('route-sample')


@api.route('/title')
def get_title(doc):
	return routes.make_response(data=doc.Title)

ここまでコードしたらpyRevitをリロードしてみましょう。
自身のブラウザで http://localhost:48884/route-sample/title に飛んでみてください。
以下の画像のように表示されていたらpyRevit側は成功です。

5.2 Streamlit側のコード

streamlit側ではpyRevit Routeで送られたJson形式のデータを読み込みにいきます。ここではrequestsを使って読み込んでみましょう。
動かす前に以下のコードを実行しておいてください。

pip requests

空のディレクトリを用意して、その中にapp.pyを用意します。
コードは以下のようにします。

import streamlit as st
import requests 

BASE_URL = 'http://localhost:48884/route-sample/'

def get_title():
	url = BASE_URL + 'title'
	res= requests.get(url)
	if res.status_code == 200:
		return res.json()

st.title(get_title())

app.pyのディレクトリ上で以下のコマンドを実行します。

streamlit run app.py

以下のように表示されたら成功です。

6. プロジェクトに含まれるレベルを表形式で表示する

pandasのDataFrameを用いて表を作成します。

6.1 pyRevit側

まずはpyRevit側でレベルの名前とエレベーションを取得します。
この段階で、リストをエレベーションでソートしておきます。

@api.route('/levels')
def get_levels(doc):
	level_list = []
	levels = db.Collector(
		of_category='Levels',
		is_not_type=True).get_elements()
	for level in levels:
		level_dict = {}
		level_dict['name'] = level.name
		level_dict['Elevation']= level.Elevation * 304.8
		level_list.append(level_dict)
	sorted_level_list = sorted(level_list, key=lambda x:x['Elevation'])
	return routes.make_response(data=sorted_level_list)

##6.2 Streamlit側
Streamlit側では表を表示する形式を以下のようにします。

def get_levels():
	name_list = []
	elevation_list = []
	url = BASE_URL + 'levels'
	res= requests.get(url)
	if res.status_code == 200:
		for l in res.json():
			name_list.append(l['name'])
			elevation_list.append(l['Elevation'])
		level_tuple = list(zip(name_list, elevation_list))
		chart_data = pd.DataFrame(
			level_tuple,
			columns = ['Level Name','Elevation'])
		return chart_data

st.subheader(" レベル表 ")
st.dataframe(get_levels())

成功すると以下のように表示されます。

7. プロジェクトに含まれる窓のタイプ別個数をグラフで表示

pyRevit側

今回はファミリ名でバーチャートを分けてみます。
ファミリ名と個数をそれぞれ取得してデータを送ります。

@api.route('/furniture')
def get_furnitures(doc):
	furnitures = db.Collector(
		of_category='Furniture',
		is_not_type=True).get_elements()
	furniture_dict = {}
	for w in furnitures:
		if w.Symbol.FamilyName in furniture_dict.keys():
			furniture_dict[w.Symbol.FamilyName] += 1 
		else:
			furniture_dict[w.Symbol.FamilyName] = 1
	return routes.make_response(data=furniture_dict)

Streamlit側

def get_furnitures():
	url = BASE_URL + 'furniture'
	res= requests.get(url)
	if res.status_code == 200:
		furniture_dict = res.json()
		chart_data = pd.DataFrame(
			furniture_dict.values(),
			index=furniture_dict.keys())
		return chart_data

st.subheader(" 家具ファミリ別 ")
st.bar_chart(get_furnitures())

成功すると以下のように表示されます。