Skip to main content

Tutorial - Integrate Rhino/Grasshopper

note

Estimated time: 45 minutes
Difficulty level: Intermediate


  • Not a reader? feel free to follow this tutorial as a video

    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:

    1. Setup integration with Grasshopper
    2. Build the VIKTOR app
    3. Use your own Grasshopper model

    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 and downloads

    Prerequisites
    • You have installed VIKTOR on your computer
    • You have some experience with reading Python code
    • You have some experience with Rhino/Grasshopper
    Required Downloads
    SDK version

    This code requires support for the GrasshopperAnalysis, which is available since SDK v14.8.0. Make sure use this SDK version or higher in your requirements.txt file.

    Explanation of setup

    Before diving into the steps, let's explain how the integration will work. See the following diagram:

    The following will happen:

    1. The user fills in input parameters in the VIKTOR UI
    2. In VIKTOR app.py these input parameters will be sent together with a Grasshopper script (sample_box_grasshopper.gh) to the worker.
    3. The Grasshopper worker will run Rhino/Grasshopper (on your local machine), based on the Grasshopper script (sample_box_grasshopper.gh) and the input parameters.
    4. The Grasshopper model generates output data, which is sent back by the worker.
    5. In VIKTOR app.py, the output data is converted into a 3dm geometry file, which 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.

    Rhino 8 - plug-ins & .NET

    In order to install some older plug-ins, you may have had to set your .NET such that it is running in .NET Framework. If you did, please change it back to the default setting (.NET Core) for the integration to work using the SetDotNetRuntime in the Rhino command line.

    1. Setup integration with Grasshopper

    A worker (integration) 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 output data back. Before we setup the worker, we must first install the Hops plugin for Grasshopper.

    Install Hops plugin

    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.

    1. Install Hops via the Package Manager in Rhino (type PackageManager on the Rhino command line and search for "Hops")

    1. 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.

    Install Grasshopper worker

    Follow these steps to install the worker:

    1. Navigate to the "My Integrations" tab in your personal settings

    2. Click "Add integration"

    3. Follow the steps provided in the modal

      3.1. Select Grasshopper

      3.2. Download the worker .msi (Microsoft Installer) and run it on the machine of choice

      3.3. Copy the generated connection key and paste it when the installer asks for it

    Connection Key

    The generated connection key should be copied immediately as VIKTOR will not preserve this data for security reasons.

    localhost port

    By default, the local RhinoCompute server runs on http://localhost:6500/, so this has been preselected in the installation wizard. If you have configured RhinoCompute to a different port, please update this accordingly during the installation.

    Once the installation has completed, the worker should start up automatically. If all went well, you will be presented with the worker terminal in which the message: "Successfully connected to the server" is displayed. In the top right corner in your viktor environment you should see a green indicator in your integrations overview, see the figure below.

    Nice work! The integration is ready to use, let's test the VIKTOR app.

    (optional) Check out Grasshopper model

    Before we start building our VIKTOR app, you might be curious to know what kind of Grasshopper model we will be integrating. If you want to check out the Grasshopper model, open the Grasshopper file (sample_box_grasshopper.gh) with the Grasshopper plugin and this should lead to the following view:

    Let's take some time to check out what is happening in the Grasshopper script:

    1. Three Hops input parameters (width, length and height) are defined based on the Get Number component of Hops.

    2. A simple box is created based on the width, length and height, which is subsequently meshed.

    3. 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.

    2. Build the VIKTOR app

    Create an empty app

    Let’s first create and start an empty app. Make sure to give your app a recognizable name, like "my-grasshopper-app".

    • Create an empty editor type app

      viktor-cli create-app my-grasshopper-app --app-type editor
    • Navigate to the app directory

      cd my-grasshopper-app
    • Add rhino3dm as dependency in the requirements.txt so that the file contents look like this.

      viktor==14.16.2
      rhino3dm
    • Install and start the app

      viktor-cli clean-start

    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.

    1. Open app.py, import viktor and add the relevant fields to your parametrization. In the end your app.py file should look like this:
    import viktor as vkt


    class Parametrization(vkt.Parametrization):
    intro = vkt.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 = vkt.NumberField('Width', default=5)
    length = vkt.NumberField('Length', default=6)
    height = vkt.NumberField('Height', default=7)


    class Controller(vkt.Controller):
    parametrization = Parametrization
    1. 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.

    First, place the sample_box_grasshopper.gh file in the 'my-grasshopper-app' folder.

    Then change the code in app.py to the code below:

    import viktor as vkt
    import json
    import rhino3dm
    from pathlib import Path


    class Parametrization(vkt.Parametrization):
    intro = vkt.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 = vkt.NumberField('Width', default=5)
    length = vkt.NumberField('Length', default=6)
    height = vkt.NumberField('Height', default=7)


    class Controller(vkt.Controller):
    parametrization = Parametrization

    @vkt.GeometryView("Geometry", duration_guess=10, x_axis_to_right=True, update_label='Run Grasshopper')
    def run_grasshopper(self, params, **kwargs):
    grasshopper_script_path = Path(__file__).parent / "sample_box_grasshopper.gh"
    script = vkt.File.from_path(grasshopper_script_path)
    input_parameters = dict(params)

    # Run the Grasshopper analysis and obtain the output data
    analysis = vkt.grasshopper.GrasshopperAnalysis(script=script, input_parameters=input_parameters)
    analysis.execute(timeout=30)
    output = analysis.get_output()

    # Convert output data to mesh
    file3dm = rhino3dm.File3dm()
    obj = rhino3dm.CommonObject.Decode(json.loads(output["values"][0]["InnerTree"]['{0}'][0]["data"]))
    file3dm.Objects.Add(obj)

    # Write to geometry_file
    geometry_file = vkt.File()
    file3dm.Write(geometry_file.source, version=7)
    return vkt.GeometryResult(geometry=geometry_file, geometry_type="3dm")

    If you now refresh your app, you should see the following:

    Now press 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 made a VIKTOR app with a Grasshopper model running behind it!

    3. 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.

    1. 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. As you can see highlighted in the image below, the names need to be exactly the same for the integration to work.

    1. Mesh your final geometry. In order for Rhino Compute to successfully export your geometry you need to mesh it because Rhino Compute can only export a mesh. If you don't, your geometry will not appear in the environment.

    2. Add the Context Bake component. The Grasshopper node Context Bake is needed to bake the model.

    Flatten your inputs

    It is recommended to flatten the inputs in your grasshopper script, especially for simpler/smaller scripts. For larger grasshopper scripts, this may still be true but it may be more efficient to use the Tree structure as input.

    Want to find out more? Check out the thread on the community.

    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 Grasshopper 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.