STUDIO TAMA


thumbnail

投稿日:2022-11-12

【Grasshopper】GhPythonからAPIを叩き、UserAttributesをDBで管理してみた。

  • #Grasshopper

  • #Rhinoceros

  • #Python

今回は、node.js で API を作成し、GhPython コンポーネントから、作成した API を叩いてみました。4 枚のパネルに対して UserAttributes を設定し、GhPython から API を叩き、CRUD 操作を一通り行い、DB で attributes を管理するといった内容になってます。

はじめに

初めに以下の前提があることを認識してから記事を読んでいただけると幸いです。

  1. 私自身、最近は Javascript を使用した開発が中心で Python は”にわか”です Rhinoceros / Grasshopper で API を叩くときに雰囲気で書いてますが、その程度なのでもしかしたら変な書き方してるかもです。そもそも今回はさほど Python 書きませんが、あらかじめご理解ください。
  2. Rhino / Grasshopper は業務でそこそこ使いますが、複雑な案件をやっているわけではありません。今回の記事を見て、「実務でこうやってんだな~」みたいには思わないようにおきおつけください。ただの思い付きでやってみただけです。(実務でどんなふうにやっているのかはむしろ僕が知りたい・・・)
  3. 今回は全体的にどんな感じでやっているかだけ解説していきます。ザックリとしか説明していないのであらかじめご了承ください。Github にソースコードは載せてます。Grasshopper のファイルも push してます。⇒こちらから

では解説していきます。

概要

thumbnail

今回の概要は上の様になってます。

  1. Grasshopper で 4 枚の Panel を生成。4 枚のパネルに対して、delivery(出荷日)の attributes を付与することを想定しています。
  2. node.js を使用し、delivery attributes の保存・取得・更新・削除する API を作成。
  3. GhPython から作成した API にリクエストを送ることで、データベースに保存した attributes を grasshopper から保存・取得・更新・削除できるようにします。
  4. Rhino モデルには Elefront で Id の attribute のみ付与し、delivery の attribute はデータベースで管理。

みたいな内容になってます。

ちなみに諸々のバージョン。

  • Rhinocero7
  • API ⇒ node.js (18.12.1) / Express(4.18.2) / Typescript( 4.8.4 ) /mongoose( 6.7.2 )
  • DB ⇒ MongoDB

ちなみにサーバーサイドの言語選定理由は、ただ単に自分がやりやすいツールを使っているだけです。お好きなサーバーサイドの言語で実装していただいて全く問題ありませんし、DB に関しても RDB 系のデータベースでもなんでもいいです。ブラウザで完結して楽だから今回 MongoDB を選定しているだけです。mongoose は mongoDB との接続を行ってくれるモジュールとなっております。

GhPython から API を叩いてみる

thumbnail

とりあえず grasshopper の GhPython コンポーネントから API を叩いてみましょう。リクエスト先は

を使用します。こちらは API サーバーになっており、リクエストを送ると適当なダミーデータを JSON で返してくれます。今回は JSON Placeholder の Users(10 ユーザーのダミーデータ)を取得してみます。

1import urllib2
2import json
3
4def fetch_data():
5
6  url = 'https://jsonplaceholder.typicode.com/users'
7
8  response = json.load(urllib2.urlopen(url))
9  for value in response:
10    print value
11
12fetch_data();

Python のモジュール urllib2 を使用し、リクエストを送ってます。json 形式でレスポンスが返ってくるので、パースしてから出力してます。上画像の様に、データが取得できているのがわかります。

このエンドポイントを、自分で作った API のエンドポイントにして諸々の処理を施していく感じです。

API 作成

thumbnail

上が作成した API となります。詳しくは説明しませんが 5 つのエンドポイントを作成しています。ソースコード興味ある方は

参照願います。

Grasshopper の実装:全体像

thumbnail
  • 上画像が Grasshopper のプログラムの全体像となっております。

Grasshopper の実装(モデリング / attributes 作成)

thumbnail

それでは Grasshopper の解説を行っていきます。

  • CreatePanel グループで三角形のパネルを 4 枚作成しています。この 4 枚パネルに attributes を与えていく予定です。(※プラグイン Lunch Box 使用しています。インストールはこちらから)
  • PanelFrame のグループではフレームを作成しています。フレームは今回 attribute を与えないので作成しなくても OK です。
  • GenerateDate のグループで与えるパネルに与える delivery attributes を生成しています(2022-11-1 ~ 2022-11-4)
  • InitialAttributes のグループでパネルに与える id と delivery の attributes を生成しています。id はわかりやすく(P-1, P-2, P-3, P-4)としています。

Grasshopper の実装( attributes を持たせた Bake )

thumbnail
  • METHOD のグループで method によって StreamFilter で処理を変えてます。POST / UPDATE / DELETE で場合分けをしている感じです。ちなみに POST は 0, UPDATE は 1, DELETE は 2 を返します。
  • Visible Attributes のグループで attribues を可視化してます。現状パネルに P1 ~ P4 の Id が振られており、2022-11-1 ~ 2022-11-4 までの deliery attributes が割り当てられてます。
  • Bake のグループで、 Elefront を使用して attributes を持たせた Bake を行ってます。attributes は Id だけ付与しており、delivery attributes は MongoDB に保存してきます。(※Elefront のインストールはこちらから)

Grasshopper の実装( POST method を実行 )

thumbnail
  • POST メソッドの処理を Ghpython コンポーネントに書いていきます。コードは以下になります。Elefront の Bake ボタンが押され、かつ StreamFilter に接続している ValueList が POST の時に実行されるようにしています。以下のプログラムを実行します。
1import urllib2
2import json
3
4def postPanel():
5
6  url = 'http://localhost:3000/api/panels/'
7  handler = urllib2.HTTPHandler()
8  opener = urllib2.build_opener(handler)
9
10  id = attributes[0]
11  delivery = attributes[1]
12
13  sendValues = {
14      "_id":id,
15      "delivery":delivery
16  }
17
18  sendValuesJson = json.dumps(sendValues).encode("utf8")
19
20  request = urllib2.Request(url, sendValuesJson)
21  request.add_header("Content-Type",'application/json')
22  response = json.load(urllib2.urlopen(request))
23  print response
24
25if method == 0 and trigger == True:
26    postPanel()
  • MongoDB を確認してみると。_id:P-1 ~ P4 までのデータに対して、delivery : 2022-11-1 ~ 2022-11-4 のデータがしっかり保存されています。
  • Rhino 側にも同時に Bake されますが、Rhino 側は Id のみ付与してます。delivery の attributes は API を叩いて取得すればいいので。
thumbnail
  • DB のすべてのデータを取得するコンポーネントも作っておきます。Botton を押すと実行されるようにしています。
thumbnail
1import urllib2
2import json
3
4def getAllPanels():
5
6  url = 'http://localhost:3000/api/panels'
7
8  response = json.load(urllib2.urlopen(url))
9  for value in response:
10    print value
11
12if excute:
13    getAllPanels();

Grasshopper の実装( PUT method を実行 ①: データの取得 )

thumbnail
  • 次に UPDATE ( PUT )を実装していきます。まずは現状のジオメトリと attributes を取得してきます。
  • getCurrentData のグループでは、Rhino 上に Bake したジオメトリを取得しています。先ほど Elefront で Bake した際 panel というレイヤ名で Bake しましたので、Elefront の Reference by Layer で panel レイヤ内のジオメトリを取得しています。その後、GetUserAttributes で付与した id の attributes を取得しています。
  • sortPanelsById のグループで、取得したジオメトリを Id 順に並べ替えています。
  • GhPython コンポーネントで、Rhino モデルから取得した Id を使用し、MongoDB に保存されている値を取得してきます。
thumbnail
1import urllib2
2import json
3
4def getAllPanels():
5
6  url = 'http://localhost:3000/api/panels/' + id
7
8  response = json.load(urllib2.urlopen(url))
9  print response
10
11  _id = response['_id']
12  delivery = response['delivery']
13
14  return _id,delivery
15
16if excute:
17    attributes = getAllPanels();

Grasshopper の実装( PUT method を実行 ②:データの更新 )

thumbnail
  • attributesUpdate のグループで、delivery attributes を更新します。上の例では、0 番目~ 3 番目まである 4 枚のパネルのうち、2 番目のパネルの搬入日を 2022-11-3 ⇒ 2022-11-1 に変更しています。(※item selector コンポーネントはプラグイン human を使用しています。インストールはこちらから)
thumbnail
  • METHOD グループの StreamFilter に、先ほど取得してきた Rhino 上のジオメトリと、更新した attributes を接続し、ValueList を UPDATE に変更します。Rhino 上の可視化した attributes で P-2 が 2022-11-1 になっているのがわかりますが、まだ Bake していないので Update はされていません。
  • GhPython で MongoDB 内の attributes を更新するリクエストを作成し実行してみます。POST の時と同様で、Bake ボタンが押され、かつ ValueList の値が UPDATE の時に実行されるようになってます。
thumbnail
1import urllib2
2import json
3
4def updatePanel():
5  id = attributes[0]
6  delivery = attributes[1]
7
8  url = 'http://localhost:3000/api/panels/'+id
9  handler = urllib2.HTTPHandler()
10  opener = urllib2.build_opener(handler)
11
12  sendValues = {
13      "_id":id,
14      "delivery":delivery
15  }
16
17  sendValuesJson = json.dumps(sendValues).encode("utf8")
18
19  request = urllib2.Request(url, sendValuesJson)
20  request.add_header("Content-Type",'application/json')
21  request.get_method = lambda: 'PUT'
22  response = json.load(urllib2.urlopen(request))
23  print response
24
25if method == 1 and trigger == True:
26    updatePanel()
  • MongoDB が更新されているか確認します。問題なく更新されいます。↓
thumbnail
  • GhPython で作成した GetAll で MongoDB に保存されている値を取得します。問題ないさそうです。Rhino 上でも問題ないようです。(ジオメトリがダブるとか、id がずれてるとか起きていないですね。)
thumbnail
thumbnail

Grasshopper の実装( DELETE method を実行 )

thumbnail
  • まずは、ジオメトリと attributes を最新の状態にします。Reference by Layer の Update を押して最新の状態にします。同時に GhPython に実装した id ごとのデータを取得するスクリプトも走り attributes が最新の状態になります。
thumbnail
  • DeleteGeometry のグループでいらなくなったジオメトリと attributes をリストから除外しています。上の例では 0 番目のパネルを削除しています。StreamFilter に 0 番目を削除したリストを接続し、ValueList を DELETE にすると、0 番目のパネルが消えてるかと思います。まだ Bake していないの反映はしていません。
  • GhPython コンポーネントに attributes を DELETE するリクエストを書いて実行してみます。
thumbnail
1import urllib2
2import json
3
4def deletePanel():
5
6  id = attributes[0]
7
8  url = 'http://localhost:3000/api/panels/'+id
9
10  handler = urllib2.HTTPHandler()
11  opener = urllib2.build_opener(handler)
12
13  request = urllib2.Request(url)
14  request.add_header("Content-Type",'application/json')
15  request.get_method = lambda: 'DELETE'
16  response = json.load(urllib2.urlopen(request))
17  print response
18
19
20if method == 2 and trigger == True:
21    deletePanel()
  • MongoDB も問題なく反映されており P-0 が削除されています。
thumbnail
  • GetAll と Rhino も確認。どちらも問題ないようです。
thumbnail
thumbnail

以上になります。かなりざっくりした説明になりましたが、ご興味ある方は

に Grasshopper ファイルも push しとくのでのぞいてみてください。元々は、GoogleDrive に格納済みのスプレッドシートを Grasshopper 上で参照する必要があり、API を叩いていたら今回の様なこともやってみようかなと思った次第です。(※スプシの方もそのうちブログ書くと思います。 →  書きました。ご興味あれば以下のリンクご参照ください。)やってることは、ただ GhPython コンポーネントから API を叩く、それだけです。node.js でやってることも基本的なことばかりです。javascipt の基礎知識は必要ですが、適当に udemy で node.js の講座を購入してやれば、簡単に作れます。そのうち役に立ちそうだなと思い記事にしときました。是非ご参考ください。

thumbnail

【Grasshopper】Hopsを使用してSpreadSheetのデータをGrasshopperから取得する

Hopsを使用してSpreadSheetのデータをGrasshopperから取得する

【参考文献】

以上

thumbnail

icon

目 次