Tutorial - Integrate Rhino/Grasshopper
Estimated time: 45 minutes
Difficulty level: Intermediate
Introduction
Welcome to this tutorial on integrating Grasshopper with VIKTOR! In this tutorial, you will learn how to create a VIKTOR web app with a Grasshopper model running behind it by the following steps:
By the end of this tutorial, you will have created a simple VIKTOR application that creates a geometry and data view of a simple box, see the image below:
So, let's get started and learn how to create a VIKTOR app based on a Grasshopper model!
Pre-requisites
- You have installed VIKTOR on your computer
- You completed Create your first app section
- You have some experience with reading Python code
- You have some experience with Rhino/Grasshopper
Explanation of setup
Before diving into the steps, let's explain how the integration will work. See the following diagram:
The following will happen:
- The user fills in input parameters in the VIKTOR UI
- In VIKTOR app.py these input parameters will be saved in the input.json file, and sent to the worker.
- The Generic worker will run Rhino/Grasshopper (on your local machine), based on a Grasshopper script (sample_box_grasshopper.gh) and the input parameters (input.json).
- The Grasshopper model generates a 3D file (geometry.3dm), which is sent back by the worker.
- In VIKTOR app.py, the 3dm geometry file will be sent back to the VIKTOR UI.
Now let's setup everything to get this running! We will go through the diagram from right to left.
1. Setup a folder locally and test
Install Hops
Hops is a plugin for Grasshopper, which will be used to make it possible to call the Grasshopper script externally, using a local Rhino Compute server.
- Install Hops via the Package Manager in Rhino (type
PackageManager
on the Rhino command line and search for "Hops")
- Make sure Rhino Compute will be launched at start up. In Grasshopper, go to
File -> Preferences
and check the following settings:
We recommend to uncheck Hide Rhino.Compute Console Window, because you can then easily see if Rhino Compute is running and debug when necessary.
The full documentation of Hops can be found in the Rhino documentation.
Create a folder where Rhino/Grasshopper runs
Create a folder where the Rhino/Grasshopper models will run. Make sure it is a location where you have access rights, for example: C:\Users\your-name\viktor-grasshopper
.
Download the following zip file, unzip the folder and copy the 3 files to the folder you just created: files-grasshopper-tutorial.zip
Check the Rhino/Grasshopper model
Now open the Grasshopper file (sample_box_grasshopper.gh
) with the Grasshopper plugin. This should lead to the following view:
Let's take some time to check out what is happening in the Grasshopper script:
Three Hops input parameters (
width
,length
andheight
) are defined based on theGet Number
component of Hops.A simple box is created based on the width, length and height, which is subsequently meshed.
The mesh is baked into Rhino using the
Context Bake
component of Hops.
If you change the input parameters, you will see that a box is drawn in Rhino. With this setup, we are ready to run this Grasshopper file from a Python script.
Test run_grasshopper.py
The VIKTOR worker will automatically run the Grasshopper file using the local Rhino Compute server, by the Python file (run_grasshopper.py
) that you placed in the folder:
When you open the Python file with an IDE (for example Pycharm), you should see the following code:
# Pip install required packages
import os
import json
import compute_rhino3d.Grasshopper as gh
import compute_rhino3d.Util
import rhino3dm
# Set the compute_rhino3d.Util.url, default URL is http://localhost:6500/
compute_rhino3d.Util.url = 'http://localhost:6500/'
# Define path to local working directory
workdir = os.getcwd() + '\\'
# Read input parameters from JSON file
with open(workdir + 'input.json') as f:
input_params = json.load(f)
# Create the input DataTree
input_trees = []
for key, value in input_params.items():
tree = gh.DataTree(key)
tree.Append([{0}], [str(value)])
input_trees.append(tree)
# Evaluate the Grasshopper definition
output = gh.EvaluateDefinition(
workdir + 'sample_box_grasshopper.gh',
input_trees
)
# Create a new rhino3dm file and add resulting geometry to file
file = rhino3dm.File3dm()
output_geometry = output['values'][0]['InnerTree']['{0}'][0]['data']
obj = rhino3dm.CommonObject.Decode(json.loads(output_geometry))
file.Objects.AddMesh(obj)
# Save the rhino3dm file to your working directory
file.Write(workdir + 'geometry.3dm', 7)
As can be seen in the imports, two packages are necessary: rhino3dm
and compute-rhino3d
. These packages can be installed via pip:
pip install rhino3dm
pip install compute-rhino3d
Note that Rhino the highest Python version that Rhino supports is 3.10: we recommend to use a Python version between 3.7 and 3.10. Make sure that one of these Python versions is installed on the computer where you will run Rhino/Grasshopper.
Let's test if the Python file works:
- Make sure Rhino and Grasshopper are running, such that the local Rhino Compute server is also running. You don't have to open a Grasshopper file.
- Run the
run_grasshopper.py
from your IDE
You should now see that the following flow runs automatically: Rhino Compute is running with the input parameters read from input.json
and the output file geometry.3dm
is created in the same folder.
If this works correctly: great! Now you are ready for the next step.
2. Setup the worker
A worker is a program that connects VIKTOR with third-party software to execute tasks and retrieve results through the platform. In this case, the worker will start Rhino/Grasshopper with the input data and send the resulting geometry back.
Install worker
Follow these steps to install the worker:
- Go to your VIKTOR environment via the browser and log in:
- Free account: cloud.viktor.ai
- Company account: your-company.viktor.ai
- Create the worker in your VIKTOR environment
- Step 1 Go to the "Workers" tab
- Step 2 Click the "Create worker" button (top right)
- Step 3 Fill in the description, allocation to specific and use your development workspace
- Step 4 Click "Create". You will get the following pop-up (see figure below). Keep this window open, you will need the credentials in the next step.
Download and install the Generic worker using this guide. Select the Generic integration. The installer starts an installation wizard from which the worker can be configured. Administrator rights on the machine are required to perform the installation.
Specification of the installation directory. The standard directory that is used for the installation is:
C:\Program Files\VIKTOR\VIKTOR for <application> <software package> <version>
- Configuration of the worker. Using the installation wizard you will be asked to fill the required information step-by-step. During this installation wizard you are asked for the credentials you generated in step 1.
Setup worker
The setup of the worker is defined in the config.yaml file, which can be found in the same folder where the worker is installed (see last chapter). Open the config.yaml
file (using for example Notepad) and replace the text with the following:
executables:
run_grasshopper:
path: 'C:\Users\your-name\AppData\Local\Programs\Python\Python310\python.exe'
arguments:
- 'C:\Users\your-name\viktor-grasshopper\run_grasshopper.py'
workingDirectoryPath: 'C:\Users\your-name\viktor-grasshopper'
maxParallelProcesses: 1 # must be 1
- Make sure to set the path correctly to the Python executable. Tip: search for
python.exe
in the Windows Search Bar and click Open file location. Note: the highest supported Python version is 3.10. - Make sure to set the arguments correctly to the
run_grasshopper.py
file. - Make sure to set the workingDirectoryPath correctly to the folder you created in step 1.
Save the file when you have defined the paths correctly.
Start up worker
Once you have saved your config.yaml
file, you can run viktor-worker-generic.exe
. Be sure to run the executable with
Administrator rights. If all went well, you will be presented with the worker terminal in which the message: "Successfully
connected to the server" is displayed. Also in in top right corner in your viktor environment you should see a green indicator
in your worker overview, see the figure below.
Nice work! The integration is ready to use, let's setup the VIKTOR app.
3. Build the VIKTOR app
Create an empty app
Let’s first create and start an empty app. If you don't remember how this worked you can check out the first few steps of the Create your first app tutorial. Make sure to give your app a recognisable name, like "my-grasshopper-app".
Here a short summary of the process.
# Create an empty editor-type app
> viktor-cli create-app my-grasshopper-app --app-type editor
# Navigate to the app directory and install the app
> cd my-grasshopper-app
> viktor-cli install
# Clear your database just to be sure
> viktor-cli clear
# And start the app!
> viktor-cli start
Please be aware that the create-app
function sets the newly created app to use the latest SDK-version. This tutorial requires an SDK version of at least 14.4.0.
Open your app in your browser by visiting the URL shown in the command-line shell:
Add input fields
We will add 3 input fields to our app: width
, length
and height
. We will use Numberfield
for this.
- Open
app.py
, and add the relevant fields to your parametrization. Don't forget to import the necessary fields. In the end yourapp.py
file should look like this:
from viktor import ViktorController
from viktor.parametrization import ViktorParametrization
from viktor.parametrization import NumberField
from viktor.parametrization import Text
class Parametrization(ViktorParametrization):
intro = Text("## Grasshopper app \n This app parametrically generates and visualises a 3D model of a box using a Grasshopper script. \n\n Please fill in the following parameters:")
# Input fields
width = NumberField('Width', default=5)
length = NumberField('Length', default=6)
height = NumberField('Height', default=7)
class Controller(ViktorController):
label = 'My Entity Type'
parametrization = Parametrization
- Refresh your app, and you should see the input fields there.
Add the Python code to run Grasshopper
Now the app code can be extended to integrate the Grasshopper script. Change the code in app.py
to the code below:
from io import BytesIO
import json
from viktor import ViktorController
from viktor.parametrization import ViktorParametrization
from viktor.parametrization import NumberField
from viktor.parametrization import Text
from viktor.external.generic import GenericAnalysis
from viktor.views import GeometryView
from viktor.views import GeometryResult
class Parametrization(ViktorParametrization):
intro = Text("## Grasshopper app \n This app parametrically generates and visualizes a 3D model of a box using a Grasshopper script. \n\n Please fill in the following parameters:")
# Input fields
width = NumberField('Width', default=5)
length = NumberField('Length', default=6)
height = NumberField('Height', default=7)
class Controller(ViktorController):
label = 'My Entity Type'
parametrization = Parametrization
@GeometryView("Geometry", duration_guess=10, update_label='Run Grasshopper')
def run_grasshopper(self, params, **kwargs):
# Create a JSON file from the input parameters
input_json = json.dumps(params)
# Generate the input files
files = [('input.json', BytesIO(bytes(input_json, 'utf8')))]
# Run the Grasshopper analysis and obtain the output files
generic_analysis = GenericAnalysis(files=files, executable_key="run_grasshopper", output_filenames=["geometry.3dm"])
generic_analysis.execute(timeout=60)
threedm_file = generic_analysis.get_output_file("geometry.3dm", as_file=True)
return GeometryResult(geometry=threedm_file, geometry_type="3dm")
This code requires support for 3dm files, which is available since SDK v14.4.0. Make sure use this SDK version or higher in your requirements.txt
file.
If you now refresh your app, you should see the following:
After pressing the Run Grasshopper button (be sure that the worker, Rhino and Grasshopper are running), you should see that Rhino Compute is run by the worker which will result in the following:
Congratulations, you now have a made a VIKTOR app with a Grasshopper model running behind it!
4. Use your own Grasshopper model
If you would like to integrate your own Grasshopper model in VIKTOR, you can adapt the app you just created. Take the following steps:
Extend your Grasshopper model
As explained in this section, some specific things need to be defined in the Grasshopper model to make the integration work.
Connect your specific input parameters by Hops components. In order to update the parameters via Rhino Compute, create Hops Get Components for the parameters you want to update.
Add the Context Bake component. The Grasshopper node Context Bake is needed to bake the model.
After implementing these changes, check if the Python script still runs successfully (run run_grasshopper.py
). Be aware that in the Python file, the name of the Grasshopper file is defined: change this name to match with your file name.
Adjust the VIKTOR app code
In the VIKTOR app code adjust the parametrization to match with your required input parameters.
The rest of the code should not require any changes to work.
To infinity and beyond
Great work! You are now able to create an app that can integrate with an external installation of Grasshopper through a Generic Worker!
Of course, the journey doesn't end here. Check out some of our other tutorials or go to the next section where you can see the different paths you can follow in your journey to learn more about VIKTOR.