Introduction
We are going to need smart engineering solutions to solve our planet’s problems (and soon in other celestial bodies in our solar system) in a smart and scalable manner. Parametric programming is a fantastic approach to optimize efficient engineering methods and achieve those goals.
We recently came across a very interesting platform named VIKTOR which introduces smart app development for engineering with our favorite programming language: Python. The Python-based software is applicable to so many disciplines in the engineering and applied science fields. From material science to organic chemistry, civil engineering to mechanical engineering, Viktor offers an impressive toolbox and takes care of tedious processes such as app hosting, app deployment, intellectual property management and server administration.
In this mini-tutorial we will demonstrate how to create parametric design elements using VIKTOR and Python. VIKTRO also helps package, save, deploy and distribute your engineering app with your colleagues or clients and it can be useful for both engineers and engineering-related business teams as well.
Tutorial: Creating Web Apps with VIKTOR (powered by Python)
Creating a web app is an awesome way to let people interact with your Python code because people everywhere in the world can access it; even the ones without any Python skills can use a graphical interface. It brings a whole another level of visualization and interactivity to your engineering project. First, we will ask VIKTOR to create a folder with an empty app containing all files you need, and then install it.
Some years ago, you would be right, but nowadays, the low-code app development platform VIKTOR makes it so easy that virtually anyone with Python knowledge can do it.
In this tutorial, we will guide you to build your very first app with VIKTOR. We will start with a blank app and create an interactive 3D model of a radio tower step by step. So, let’s get started!
Note: In case you need it, we included a complete web app code at the end of this tutorial.
Contents:
- Creating and starting an empty app
- Creating a 3D model
- Adding input fields
- Connecting the input fields to the 3D model
- Adding a Sphere
- Adding the mast
- Adding Materials
- What is next?
- All code together
Prerequisites
- A free VIKTOR account
- Installing the free VIKTOR library based on the instructions you receive by mail after making an account
- Some Python programming experience
- Ability to write and use functions
(You are always welcome to refer to our Python User Functions Exercises and the relevant lesson here as well as any other Python lessons, tutorials and exercises we have to reinforce your programming proficiency.)
Installing VIKTOR
Before we get started, we need to download and install VIKTOR. VIKTOR is the platform that will help us create and host the web app using nothing but Python.
Here, you can create your VIKTOR account for free. Just follow the installation instructions which are pretty straightforward. This will take approximately 10 mins.
Creating, installing and starting an empty app
First, we will first ask VIKTOR to create a folder with an empty app containing all files
you need, and then install it. We will use this app as a basis to make your app. So, let’s get started!
- In the file explorer, go to the location where you like to store this and other future apps. Let’s assume the folder is called ‘viktor-apps’.
Right-click
in this folder and click on ‘Open in Terminal’ (or similar, e.g. ‘Open PowerShell window here’) to open the command-line shell, as in the image below. Note that in older versions of Windows, you may need toShift + Right-click
on the folder.
- On the command line, write the following command:
viktor-cli create-app tower-app
This command creates an app with the name ‘tower-app’. After executing the command, you will find a folder called ‘tower-app’ inside the ‘viktor-apps’ folder.
1. In the PowerShell navigate to the ‘tower-app’ folder:
cd tower-app
2. Before installing a new app, you need to clear the database by running the following command:
viktor-cli clear
3. Now you can install your app using the command below. Installation can take up to 3 minutes, so just have a little patience and read the information below.
viktor-cli install
The command tells VIKTOR to install the app stored inside the folder where you run the command. That is why we ask you to navigate to the app folder first.
4. Start the app with:
viktor-cli start
Congratulations, your app is up and running! However, do not close your command-line shell; otherwise, your app will stop.
5. Open your app in your browser by visiting VIKTOR cloud as explained in the command-line shell
6. After logging in, open the “Development” card. Great, your app is up and running. Now let’s go to the fun part: start building the 3D model!
Creating a 3D model
In this part of the tutorial, we will create a 3D model of the radio tower using the geometry module. Before we start building the 3D model, let’s check out what the current application looks like.
In your browser,
- Click on “Create”.
- Fill in a name in the pop-up
- Click “Create and open”
You should now see an empty page. So let’s start creating our 3D model.
Add a 3D model to your app
First, we will visualize the base of the radio tower. The base will just be a cylinder, which will have a height and a diameter. The first part is a bit slow, but I promise that we will draw the rest of the tower at lighting speed.
- Go to the folder
tower-app
and openapp.py
in your favourite code editors. - Check
app.py
so that it looks like this:
from viktor.core import ViktorController
from viktor.parametrization import ViktorParametrization
class Parametrization(ViktorParametrization):
pass
class Controller(ViktorController):
label = 'VIKTOR Tutorial'
parametrization = Parametrization
3. On the top, import some additional functions we will need to create the app:
from viktor.geometry import Point,Line,CircularExtrusion,Material,Color
from viktor.views import GeometryView,GeometryResult
4. First we will create a geometry view
to show your 3D model and define a function to draw everything. We do this inside your controller like this.
...
class Controller(ViktorController):
label = 'VIKTOR Tutorial'
parametrization = Parametrization
@GeometryView("3D", duration_guess=1)
def visualize_tower(self, params, **kwargs):
"""Creates the 3D view and visualizes the Radio Tower"""
return GeometryResult()
- Now we will start drawing. First, let’s define 2 reference points we need for our design:
...
@GeometryView("3D", duration_guess=1)
def visualize_tower(self, params, **kwargs):
"""Creates the 3D view and visualizes the Radio Tower"""
# Reference points
base_start = Point(0, 0, 0) #<--- Add this lines
base_end = Point(0, 0, 50) #<--- Add this lines
return GeometryResult()
- To create your base of the tower, we will use
CirculerExtrusion
, which draws a cylinder following a line between the points base_start and base_end. Under the two point we just created add:
# Create tower base
line = Line(base_start, base_end)
base = CircularExtrusion(diameter=5, line=line)
return GeometryResult(base) # <--- don't forget to change this line
- If everything went right, you should be able to see the cylinder in your app. Save the app.py file, go to your app and refresh the page.
Python code up to cylinder creation
In case something went wrong, here you can see the complete code so far. Just copy/paste it in app.py
and everything should work.
from viktor.core import ViktorController
from viktor.parametrization import ViktorParametrization
from viktor.geometry import Point, Line, CircularExtrusion, Cone, Sphere, Material, Color
from viktor.views import GeometryResult, GeometryView
class Parametrization(ViktorParametrization):
pass
class Controller(ViktorController):
label = 'VIKTOR Tutorial'
parametrization = Parametrization
@GeometryView("3D", duration_guess=1)
def visualize_tower(self, params, **kwargs):
"""Creates the 3D view and visualizes the Radio Tower"""
# Reference points
base_start = Point(0, 0, 0)
base_end = Point(0, 0, 50)
# Create tower base
line = Line(base_start, base_end)
base = CircularExtrusion(diameter=5, line=line)
return GeometryResult(base)
Adding input fields
We created a 3D model in the last section, but what if you want a user to change the geometry dynamically? Using VIKTOR’s input fields you can. Let’s add a few input fields to change the length, width and height of your cylinder.
- Let’s import the
NumberField
we need. At the top of you code add:
from viktor.parametrization import NumberField
- Under
class Parametrization(ViktorParametrization):
we will add 2 fields to change the dimensions of the cylinder, and don’t forget to eliminatepass
. You code should look like this:
...
class Parametrization(ViktorParametrization):
"""Parametrization of the Radio Tower"""
# Base of the tower
base_height = NumberField("Height base", default=50, min=1)
base_diameter = NumberField("Diameter base", default=3, min=1)
#pass <---- DELETE THIS LINE
...
- Again, save the
app.py
file. Go to your app, refresh the page and see theNumberField
s appear in your app.
Did you notice that changing the values does not modify the 3D model? This is because we have not connected the NumberField
s to your 3D model yet. We’ll do this next.
All code toghter so far
from viktor.core import ViktorController
from viktor.parametrization import ViktorParametrization, NumberField
from viktor.geometry import Point, Line, CircularExtrusion, Cone, Sphere, Material, Color
from viktor.views import GeometryResult, GeometryView
class Parametrization(ViktorParametrization):
"""Parametrization of the Radio Tower"""
# Base of the tower
base_height = NumberField("Height base", default=50, min=1)
base_diameter = NumberField("Diameter base", default=3, min=1)
class Controller(ViktorController):
label = 'VIKTOR Tutorial'
parametrization = Parametrization
@GeometryView("3D", duration_guess=1)
def visualize_tower(self, params, **kwargs):
"""Creates the 3D view and visualizes the Radio Tower"""
# Reference points
base_start = Point(0, 0, 0)
base_end = Point(0, 0, 50)
# Create tower base
line = Line(base_start, base_end)
base = CircularExtrusion(diameter=5, line=line)
return GeometryResult(base)
Connecting the input fields to the 3D model
We’ll connect the input fields to the 3D model to make it dynamic:
- Change the 3rd value of
base_end
from a static 50 toparams.base_height
and the value ofdiameter
toparams.base_diameter
as shown below:
...
@GeometryView("3D",duration_guess=1)
def visualize_tower(self, params, **kwargs):
"""Creates the 3D view and visualizes the Radio Tower"""
# Reference points
base_start = Point(0, 0, 0)
base_end = Point(0, 0, params.base_height) # <--- add params.base_height here
# Create tower base
line = Line(base_start, base_end)
base = CircularExtrusion(diameter=params.base_diameter, line=line) # <--- params.base_diameter here
return GeometryResult(base)
- Again, save the
app.py
file. This time, instead of refreshing your app, just change some input values. Did you see that? VIKTOR updated the app, and your 3D model is now dynamic!
Awesome, we already created a fully functioning parametrized model of a beam including a 3D visualisation! If you were
wondering whether this is a good time: Yes, this is a perfect moment to pat yourself on the back!
How does this work?
So what happens in the background? Each time you change an input parameter, VIKTOR reruns the corresponding code and shows the results in the view. In technical words, your code is stateless.
- All the input parameters are stored in the variable
params
. That is why it is important to pass it todef visualize_tower(self, params, **kwargs)
. params
is aMunch
, which is like a Python dictionary. You can access the data inside params using dot-style notation. So, for example, to accessheight
insideparams
, you writeparams.height
.
Adding a sphere
At the top of the tower we add a Sphere.
1. Let’s import Sphere
from viktor.geometry import Sphere
2. We will add and input field to determine the Sphere’s radius:
...
class Parametrization(ViktorParametrization):
base_height = NumberField("Height base", default=50, min=1)
base_diameter = NumberField("Diameter base", default=3, min=1)
sphere_radius = NumberField("Radius sphere", default=4, min=1) # <-- Add this line
3. Go to our @GeometryView
and add a Sphere
under the lines that define the base. Sphere
needs a point and a diameter. Don’t forget to return the Sphere at the end, so it is visualized. Your code should look like this:
@GeometryView("3D", duration_guess=1)
def visualize_tower(self, params, **kwargs):
"""Creates the 3D view and visualizes the Radio Tower"""
# Reference points
base_start = Point(0, 0, 0)
base_end = Point(0, 0, params.base_height)
# Create tower base
line = Line(base_start, base_end)
base = CircularExtrusion(diameter=params.base_diameter, line=line)
# Create tower cabin
cabin = Sphere(base_end, params.sphere_radius) # <-- Add this line
return GeometryResult([base, cabin]) # <--- put base and cabin in a list, so they are shown.
4. Again. Save the file and refresh the app.
Adding the mast
Now that you are used to VIKTOR, we ramp up the speed and quickly add the mast on top of our tower in the exact same way we have done before.
1. Import the code:
from viktor.geometry import Cone
2. Add the NumberField
for the mast height:
mast_height = NumberField("Height mast", default=30, min=1)
3. Draw a cone and don’t forget to return it so it is visualized:
# Tower top
top = Cone(diameter=params.base_diameter, height=params.mast_height, origin=base_end) # <-- Add this line
return GeometryResult([base,cabin,top]) # <-- Update this line
4. Save the file and refresh.
Adding materials
Great, we created the full 3D model of the tower, but it is looking a bit pale. Let’s add some color, we don’t want a plane crashing into it 😉
We will add color, by creating some Material
and adding them to the 3D models.
1. Import Material
and Color
:
from viktor.geometry import Material, Color
2. Add materials as constants under the imports and before the Parametrization class:
...
WHITE = Material("White", color=Color.white()) # <-- Add these lines too
RED = Material("Red", color=Color.red()) # <-- Add these lines too
class Parametrization(ViktorParametrization): # <-- this line is just for your reference
...
3. Add the materials to the different geometries we created before, as shown here:
...
# Create tower base
line = Line(base_start, base_end)
base = CircularExtrusion(diameter=params.base_diameter, line=line, material=WHITE)
# Create tower cabin
cabin = Sphere(base_end, params.sphere_radius, material=WHITE)
# Tower top
top = Cone(diameter=params.base_diameter, height=params.mast_height, origin=base_end, material=RED)
4. Save, refresh, and you should have a colorful tower:
What is next?
If you managed to get this far, you have done a great job and successfully built your first Python app with VIKTOR! VIKTOR has a large collection of functions and visualizations that await exploring. Feel free to go and check out their docs and start making your own engineering apps powered by Python.
- Explore the different Input Fields, Option Lists and buttons
- Explore the different visualizations
- See how you can change the layout and style of your app
- Learn how to generate reports automatically
- Download one of the sample apps and tweak them to your needs
- Learn more about VIKTOR’s fundamental concepts
- Look up specific VIKTOR classes and functions in the SDK reference
And if you need any help, want to request features or share your creations, you can head over to the Community Forum.
Final code for parametric Radio Tower design
Just in case, here you can find the complete code of the app:
from viktor.core import ViktorController
from viktor.parametrization import ViktorParametrization, NumberField
from viktor.geometry import Point, Line, CircularExtrusion, Cone, Sphere, Material, Color
from viktor.views import GeometryResult, GeometryView
WHITE = Material("White", color=Color.white())
RED = Material("Red", color=Color.red())
class Parametrization(ViktorParametrization):
base_height = NumberField("Height base", default=50, min=1)
base_diameter = NumberField("Diameter base", default=3, min=1)
sphere_radius = NumberField("Radius sphere", default=4, min=1)
mast_height = NumberField("Height mast", default=30, min=1)
class Controller(ViktorController):
label = 'VIKTOR Tutorial'
parametrization = Parametrization
@GeometryView("3D", duration_guess=1)
def visualize_tower(self, params, **kwargs):
"""Creates the 3D view and visualizes the Radio Tower"""
print("Params:", params)
# Reference points
base_start = Point(0, 0, 0)
base_end = Point(0, 0, params.base_height)
# Create tower base
line = Line(base_start, base_end)
base = CircularExtrusion(diameter=params.base_diameter, line=line, material=WHITE)
# Create tower cabin
cabin = Sphere(base_end, params.sphere_radius, material=WHITE)
# Tower top
top = Cone(diameter=params.base_diameter, height=params.mast_height, origin=base_end, material=RED)
return GeometryResult([base, cabin, top])
Now although this web application is pretty simple, it’s effective and useful. Furthermore, this implementation opens a whole new world of opportunities to design engineering apps using minimal Python code base with VIKTOR which can be applied to pretty much any concept under engineering and science subdomains.
VIKTOR takes care of the cybersecurity, hosting, server administration, management of intangible assets such as intellectual property and low-level programming and the result is an intuitive app creation process which can hopefully yield fruitful discussions and/or presentations in projects with parametric design elements.
We will be publishing a number of professional Python tutorials in near future to continue demonstrating Python’s potential in sophisticated use cases in the field and help you gain inspiration that can result in real world outcomes.
You can find the Python source code and information regarding dependencies of this app at our Github Repository: Python-3D-Tower-Web-App source code.
Guest Author
Anande takes "Automate the Boring Stuff" philosophy by heart and contributes to increase efficiency in engineering applications with smart Python-based parametric design solutions @VIKTOR.